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

How to properly notify the datagrid that its data set is outdated?

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

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

属性 AllThings 是否必须为 ObservableCollection 类型,或者与 IEnumerable? (将来,如果数据库 中的相关更改 目前没有任何问题,我可能想更新网格。)

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

在public接口上暴露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?

WPF 中的更改通知基于 INotifyPropertyChanged。

对于消费者(您的 DataGrid)来说,它只是一个事件(PropertyChanged),当某些更改发生时触发。绑定引擎将相应地刷新 DataGrid。

您必须在 ViewModel 中实现 INotifyPropertyChanged,并根据需要触发事件(即在用户按下 "reload data" 按钮后)

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 更进一步,检测单个元素的插入或删除并只允许刷新它们。但它不会检测现有元素的变化(即如果现有汽车的速度发生变化)。

要检测和刷新现有元素更改,您必须对单个元素(即 class 汽车)实施 INotifyPropertyChanged。

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

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