2017-08-11 101 views
4

我有一个DataGrid,ViewModel中的Product类型的ObservableCollection和EventToCommand的实现,如下所示。 我想从数量和成本列的产品更新总列,并保存更改,而不使用邪恶代码背后或Windows窗体DataGridView。 我该如何做到这一点? 的Datagrid:无法更新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> 

然后在视图模型

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(); 
    } 

然后在型号:

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(); 
    } 
} 

数据网格是装的产品,但没有更新的总时,成本和数量变化。此外,不保存在数据库

+0

如果您的模型Total setter正在实现INotifyPropertChanged接口(未显示),那么我可以想到的唯一建议是将UpdateSourceTrigger = PropertyChanged添加到您的绑定中。 – stuicidle

+0

当ViewModel中没有这样的属性时,为什么要将DataGrid的ItemsSource绑定到名为ExamsList的属性?或者你在例子中忘记了这个属性? –

+0

@SebastianRichter这是一个错字。但是,这不是问题来自 – KMarto

回答

0

输出将是这样的: - enter image description here

更改XAML中喜欢下面给出

<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> 

并在视图模型,你绑定像

public BindingList<Product> ProductList 
{ 
get 
    { 
    return _proxy.ProductList; 
    } 
} 

和EndEdit中命令应执行以下功能

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); 
} 

你IDataService可以公开绑定列表像

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(); 
     } 
    } 

的Context.Save将节省你的代码。

+0

请根据您的需要重构。 :) – Ramankingdom

+0

任何人都可以解释为什么。其标记不作为没有测试的答案。这是工作解决方案 – Ramankingdom

+0

让我测试我将它作为答案的代码忽略downvoters – KMarto

2

的变化对于在DataGrid“总”列得到更新,该Product类应实现INotifyPropertyChanged接口,提高PropertyChanged事件的Total属性:

private double _total; 
public double Total 
{ 
    get { return _total; } 
    set { _total = value; OnPropertyChanged("Total"); } 
} 

并且为了能够将值保存到数据库中,您需要将Total属性映射到数据库表中的列,就像您(希望)对其他列做过一样。

+0

首先,我无法绑定到单个属性,因为它是一个项目列表。另外,在MVVM灯中,'Set(ref,_property,value)'实现INotifyPropertChanged。 – KMarto

+0

您已经绑定到DataGridTextColumn中的singel属性...并且它是应调用Set方法的Product类的Total属性的setter,而不是MyProduct属性。 – mm8

+0

这个项目我绑定来自'ObservableCollection '这样的项目的可观察集合,所以当我绑定时,我绑定到像Product.Price这样的集合中的一个项目的属性。我是否需要创建另一个单独的项目,如果有,数据如何加载到网格?我可能会错过你的答案。 – KMarto