我的 DataGrid 控件绑定到视图模型及其getter中 ListCollectionView 的实例,我检查基础属性 AllThings 。到目前为止,支持字段 _allThings 的填充已在视图模型的构造函数中执行,并且由于数据库中的数据仅在夜间更改,因此完全足够。
但是,截至目前,将会创建 Thing 的新实例并将其射入数据库。假设用户单击触发方法 UpdateData(Object,RoutedEventArgs)中处理的事件的按钮,重新呈现数据网格的适当方法是什么?
AllThings 属性是否必须属于 ObservableCollection 类型,或者 IEnumerable 是否足够? (将来我可能想更新网格,如果相关的内容在数据库中发生,那么它没有任何问题。)
我对正确方法如此好奇的原因是数据的来源不同。通常,数据来自对导致新数据可用事件的相同控件的绑定。在这里,控件(按钮)将通知有一些新数据,但它来自另一个源 ,即数据库。我不确定是否应该以不同方式处理它,如果是,那么如何处理。
答案 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?