I am trying to Save Data to database.
Suppose I have a Table Named Customers
having three fields:
Id
FirstName
LastName
I have created my models using ADO.Net Entity Data Model.
Here is my ViewModel code
public class myViewModel : INotifyPropertyChanged
{
private string _firstName;
public string FirstName
{
get
{
return _firstName;
}
set
{
_firstName = value;
OnPropertyChanged("FirstName");
}
}
private string _lastName;
public string LastName
{
get
{
return _lastName;
}
set
{
_lastName = value;
OnPropertyChanged("LastName");
}
}
protected virtual void OnPropertyChanged(string PropertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(PropertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Here is my MainWindow.xaml file:
<Window x:Class="Lab_Lite.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:Lab_Lite.ViewModels"
Title="MainWindow" Height="350" Width="525" WindowState="Maximized">
<Window.DataContext>
<vm:MainWindowViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="FirstName" />
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding FirstName, Mode=TwoWay, UpdateSourceTrigger=Explicit}" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="LastName" />
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding LastName, Mode=TwoWay, UpdateSourceTrigger=Explicit}" />
<Button Grid.Row="2" Grid.Column="1" Content="Save" />
</Grid>
</Window>
I have got two problems here:
1. How my ViewModel knows that FirstName property declared in ViewModel is
referenced to FirstName Column in my database?
2. How to save changes to database when UpdateSourceTrigger is set to Explicit?
I think I have found the answer to 2nd question upto some extent using Command. But I dont know if it is right or not as I dont know the answer to my first question.
Update:
Suppose I have two tables like this:
Customer:
CustomerID
Name
GenderID //Foreign Key
Gender:
GenderID
Value
Now what should be the value of CurrentCustomer.Gender
in SaveCustomerChanges
Method?
I highly recommend you use a ORM like Entity Framework (EF) using database-first since you've already created a database. Entity Framework will create your POCOs (model classes, Plain Old C# Objects) automatically for you and will also create a class named **YourDbName**Context
which is your DbContext
. At that point your application will create an instance of you context each time you run your app, and you will be able to access your database using the context. EF will also keep track of any changes you make so here is how you problem would be solved:
EF generates POCO:
public partial class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
In your viewmodel you can retrieve a List<Customer>()
from your database.
public List<Customer> Customers { get; set; } //Load from context in constructor, really though you should do it in a service layer
public Customer CurrentCustomer { get; set; } //Current customer you need to edit
So now you have two options in the viewmodel:
In order to be natural MVVM you shouldn't bind CurrentCustomer to the view. That doesn't follow the pattern. In order to fix this, you create separate properties, just like you have above, and you can either return CurrentCustomer.PropertyName
in the getter and use that in the setter like so:
public string FirstName
{
get
{
return CurrentCustomer.FirstName;
}
set
{
CurrentCustomer.FirstName = value;
OnPropertyChanged("FirstName");
}
}
By doing this you won't have to worry about mapping the viewmodel property to the POCO property, however any change you make in the view will now cause Entity Framework to track the change, in which case all you need to do now in the save method is call dbContext.SaveChanges();
.
If you want to be able to do any kind of cancel or undo then keep your properties set up the way you have it now:
private string _firstName;
public string FirstName
{
get
{
return _firstName;
}
set
{
_firstName = value;
OnPropertyChanged("FirstName");
}
}
and in your save method you will have to map the viewmodel properties to the CurrentCustomer's properties will should then cause a change to be tracked:
private void SaveCustomerChanges()
{
//Could use Automapper to handle mapping for you.
CurrentCustomer.FirstName = this.FirstName;
CurrentCustomer.LastName = this.LastName;
dbContext.SaveChanges(); //dbContext will be named diff for you
}
At this point the changes should have gone through and updated the database tables.
Now if you're not using Entity Framework, you will need to set up some kind of data access layer to which you can pass in a Customer
object and then you will need to retrieve that object from your database and update its values.
Check out this as well!
EDIT:
To call SaveCustomerChanges()
you will need to wire this method up using ICommand
.
First create a RelayCommand
Class:
public class RelayCommand : ICommand
{
private Action<object> _action;
public RelayCommand(Action<object> action)
{
_action = action;
}
#region ICommand Members
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_action(parameter);
}
#endregion
}
Now in your viewmodel:
public ICommand SaveChangesCommand { get; set; }
In your viewmodel constructor
SaveChangesCommand = new RelayCommand(SaveCustomerChanges);
Then wire up SaveChangesCommand in XAML:
<Button Content="Save" Command="{Binding SaveChangesCommand }" />
Now when you click Save the command should fire the SaveCustomerChanges()
method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With