Reputation: 300
I have a datagrid, an ObservableCollection of Product Types in a ViewModel and an implementation of EventToCommand like shown below. I would like to update the Total Column from the product of Quantity and Cost Column and save the changes without using the evil code behind or Windows Forms DataGridView. How can I achieve this? Datagrid:
<DataGrid x:Name="dataGrid" Margin="5,5,10,5" AutoGenerateColumns="False" HorizontalAlignment="Stretch" ItemsSource="{Binding ProductList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Stretch" Height="566" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="CellEditEnding" SourceObject="{Binding ElementName=Control}">
<cmd:EventToCommand Command="{Binding EndEdit}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<DataGrid.Columns>
<DataGridTextColumn x:Name="Id" Binding="{Binding Path=Id, Mode=TwoWay}" Header="Id"/>
<DataGridTextColumn x:Name="name" Binding="{Binding Path=Name, Mode=TwoWay}" Header="Name"/>
<DataGridTextColumn x:Name="cost" Binding="{Binding Path=Cost, Mode=TwoWay}" Header="Cost"/>
<DataGridTextColumn x:Name="Quantity" Binding="{Binding Path=Quantity, Mode=TwoWay}" Header="Quantity"/>
<DataGridTextColumn x:Name="total" Binding="{Binding Path=Total, Mode=TwoWay}" Header="Total"/>
</DataGrid.Columns>
Then in the ViewModel
private ObservableCollection<Product> _product;
public ObservableCollection<Product> MyProduct
{
get
{
return _product;
}
set
{
Set(ref _product, value);
}
}
public ProductViewModel(IDataService proxy)
{
_proxy = proxy;
LoadCommand = new RelayCommand(DoGetProducts);
EndEdit = new RelayCommand<DataGridCellEditEndingEventArgs>(DoEndEdit);
}
private void DoEndEdit(DataGridCellEditEndingEventArgs obj)
{
DataGridRow row = obj.Row;
Product p = (Product)row.Item;
p.Total = p.Cost*p.Quantity;
_proxy.SaveAll();
}
Then in the Model:
public class DataService : IDataService
{
ProductEntities context;
public DataService()
{
context = new ProductEntities();
}
public ObservableCollection<Product> GetProducts(){
ObservableCollection<Product> products = new ObservableCollection<Product>();
foreach(var p in context.Products.Tolist()){
products.add(p);
}
return products;
}
public void SaveAll()
{
context.SaveChanges();
}
}
The datagrid is loading products but not updating the Total when Cost and Quantity is changed. Also, not saving the changes in database
Upvotes: 4
Views: 2185
Reputation: 1496
Change your Xaml like give below
<DataGrid x:Name="dataGrid" Margin="5,5,10,5" AutoGenerateColumns="False" HorizontalAlignment="Stretch" ItemsSource="{Binding ProductList}" VerticalAlignment="Stretch" Height="566" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="RowEditEnding" ">
<cmd:EventToCommand Command="{Binding EndEdit}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<DataGrid.Columns>
<DataGridTextColumn x:Name="Id" Binding="{Binding Path=Id, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" Header="Id"/>
<DataGridTextColumn x:Name="name" Binding="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" Header="Name"/>
<DataGridTextColumn x:Name="cost" Binding="{Binding Path=Cost, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" Header="Cost"/>
<DataGridTextColumn x:Name="Quantity" Binding="{Binding Path=Quantity, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" Header="Quantity"/>
<DataGridTextColumn x:Name="total" Binding="{Binding Path=Total, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" Header="Total"/>
</DataGrid.Columns>
And in View Model you Bindings be like
public BindingList<Product> ProductList
{
get
{
return _proxy.ProductList;
}
}
And EndEdit Command Should execute the following function
private void ExecuteEndEdit(DataGridRowEditEndingEventArgs param)
{
var product = param.Row.Item as Product;
var result = ProductList.FirstOrDefault(p => p.Id == product.Id);
var index= ProductList.IndexOf(result);
result.Total = result.Cost * result.Quantity;
ProductList.ResetItem(index);
}
Your IDataService can Expose Binding List like
public class DataService : IDataService
{
ProductEntities context;
public DataService()
{
context = new ProductEntities();
}
public BindingList<Product> ProductList
{
get
{
//EDIT: YOU HAVE TO CALL context.Products.Load(); OR IT WILL RETURN EMPTY RESULTS
context.Products.Load();
return context.Products.Local.ToBindingList<Product>();
}
}
public void SaveAll()
{
context.SaveChanges();
}
}
The Context.Save will save your code.
Upvotes: 0
Reputation: 169400
For the "total" column in the DataGrid
to get updated, the Product
class should implement the INotifyPropertyChanged interface and raise the PropertyChanged
event for the Total
property:
private double _total;
public double Total
{
get { return _total; }
set { _total = value; OnPropertyChanged("Total"); }
}
And for you to be able to save the value to the database, you need to map the Total
property against a column in your database table, just like you (hopefully) did with the other columns.
Upvotes: 2