简体   繁体   中英

Unable to update Datagrid and save changes to database

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

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.

The output will be like this:- 在此输入图像描述

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM