如何正确通知datagrid其数据集已过时?

时间:2015-02-04 10:10:45

标签: c# wpf xaml datagrid

我的 DataGrid 控件绑定到视图模型及其getter中 ListCollectionView 的实例,我检查基础属性 AllThings 。到目前为止,支持字段 _allThings 的填充已在视图模型的构造函数中执行,并且由于数据库中的数据仅在夜间更改,因此完全足够。

但是,截至目前,将会创建 Thing 的新实例并将其射入数据库。假设用户单击触发方法 UpdateData(Object,RoutedEventArgs)中处理的事件的按钮,重新呈现数据网格的适当方法是什么?

AllThings 属性是否必须属于 ObservableCollection 类型,或者 IEnumerable 是否足够? (将来我可能想更新网格,如果相关的内容在数据库中发生,那么它没有任何问题。)

我对正确方法如此好奇的原因是数据的来源不同。通常,数据来自对导致新数据可用事件的相同控件的绑定。在这里,控件(按钮)将通知有一些新数据,但它来自另一个源 ,即数据库。我不确定是否应该以不同方式处理它,如果是,那么如何处理。

2 个答案:

答案 0 :(得分:1)

WPF中的更改通知基于INotifyPropertyChanged。

对于使用者(您的DataGrid),它只是在发生某些更改时触发的事件(PropertyChanged)。绑定引擎将相应地刷新DataGrid。

您必须在ViewModel中实现INotifyPropertyChanged,并根据需要触发事件(即在用户按下"重新加载数据"按钮")

public class Car
{
  public string Model;
  public int Speed;
}

class MyViewModel: INotifyPropertyChanged
{
  List<Car> cars;

  public List<Car> Cars { get {return cars;}}

  // this method is invoked from GUI, ie from an event handler or a Command of a "Reload" button
  public void ReloadData()
  {
    // do something to actually refresh cars

    // notify GUI something changed
    InternalPropertyChanged("Cars");
  }

  public event PropertyChangedEventHandler PropertyChanged;
  protected void InternalPropertyChanged(string name)
  {
    if (PropertyChanged != null)
      PropertyChanged(this, new PropertyChangedEventArgs(name));
  }
}

这样刷新整个列表,正如Weston所说,重置网格选择和位置。

ObservableCollection更进一步,检测单个元素的插入或删除,并允许仅刷新它们。但它没有检测到现有元素的变化(即现有汽车的速度变化)。

要检测并刷新现有元素更改,您必须在单个元素(即Car类)上实现INotifyPropertyChanged。

另请注意,如果您的数据库查询从头开始创建新列表(所有DB API通常都会这样做),ObservableCollection不会添加任何内容。

您应该从数据库中获取新列表,将其与现有列表进行比较,并在ObservableCollection上调用Add / Remove(这可能是不值得的)

答案 1 :(得分:0)

在公共接口上公开IEnumerable就足够了。您不希望暴露超出您需要的内容,并且公开ObservableCollection将允许外部类修改集合。

public class Model
{
    private readonly ObservableCollection<Thing> _allThings = new ObservableCollection<Thing>();

    public IEnumerable<Thing> AllThings { get { return _allThings; }}
 }

请注意,我不允许更改其引用(readonly)如果它的引用已更改(使用通知),则会导致完全刷新网格。用户将松开他们的位置,任何选择和网格都将跳到顶部。

绑定到AllThings将起作用,不再需要通知视图更改。

除此之外:ObservableCollection超过List的一个值得注意的缺点是,你不能AddRange,但要看到这个问题的解决方案:ObservableCollection Doesn't support AddRange method, so I get notified for each item added, besides what about INotifyCollectionChanging?