Wpf 检测是否修改了ObservableCollection
我在DockPanel中嵌套了一个DataGrid。DockPanel用作数据上下文:Wpf 检测是否修改了ObservableCollection,wpf,observablecollection,Wpf,Observablecollection,我在DockPanel中嵌套了一个DataGrid。DockPanel用作数据上下文: DockPanel1.DataContext = GetData(); GetData()方法返回一个ObservableCollection 可以在DataGrid以及DockPanel中嵌套的几个文本框中修改ObservableCollection。我还使用DataView浏览集合 我想检测集合是否已被修改,并在用户试图关闭应用程序而不保存数据时发出警告 是否有我可以使用的内置机制(集合或视图上的一种“
DockPanel1.DataContext = GetData();
GetData()方法返回一个ObservableCollection
可以在DataGrid以及DockPanel中嵌套的几个文本框中修改ObservableCollection。我还使用DataView浏览集合
我想检测集合是否已被修改,并在用户试图关闭应用程序而不保存数据时发出警告
是否有我可以使用的内置机制(集合或视图上的一种“IsDirty”标志)?如果没有,我想我将不得不监控所有控件并手动检测任何更改
谢谢,
Leszek为了检测集合本身的更改,您必须附加一个处理程序。如果还需要检测集合中包含的对象中的更改,则必须将处理程序附加到每个对象(前提是这些对象实现INotifyPropertyChanged) 实现基本上如下所示:
var collection = GetData();
collection.CollectionChanged += OnCollectionChanged;
...
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
AddPropertyChanged(e.NewItems);
break;
case NotifyCollectionChangedAction.Remove:
RemovePropertyChanged(e.OldItems);
break;
case NotifyCollectionChangedAction.Replace:
case NotifyCollectionChangedAction.Reset:
RemovePropertyChanged(e.OldItems);
AddPropertyChanged(e.NewItems);
break;
}
...
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
...
}
private void AddPropertyChanged(IEnumerable items)
{
if (items != null)
{
foreach (var obj in items.OfType<INotifyPropertyChanged>())
{
obj.PropertyChanged += OnPropertyChanged;
}
}
}
private void RemovePropertyChanged(IEnumerable items)
{
if (items != null)
{
foreach (var obj in items.OfType<INotifyPropertyChanged>())
{
obj.PropertyChanged -= OnPropertyChanged;
}
}
}
var collection=GetData();
collection.CollectionChanged+=OnCollectionChanged;
...
CollectionChanged的私有void(对象发送方,NotifyCollectionChangedEventArgs e)
{
开关(电动)
{
案例NotifyCollectionChangedAction。添加:
AddPropertyChanged(如新项目);
打破
案例NotifyCollectionChangedAction。删除:
移除已更改的财产(如旧物品);
打破
案例通知收集更改操作。替换:
案例通知CollectionChangedAction.Reset:
移除已更改的财产(如旧物品);
AddPropertyChanged(如新项目);
打破
}
...
}
私有void OnPropertyChanged(对象发送方,PropertyChangedEventArgs e)
{
...
}
私有void AddPropertyChanged(IEnumerable items)
{
如果(项!=null)
{
foreach(items.OfType()中的var obj)
{
obj.PropertyChanged+=OnPropertyChanged;
}
}
}
私有void RemovePropertyChanged(IEnumerable items)
{
如果(项!=null)
{
foreach(items.OfType()中的var obj)
{
obj.PropertyChanged-=OnPropertyChanged;
}
}
}
为了检测集合本身的更改,您必须附加一个处理程序。如果还需要检测集合中包含的对象中的更改,则必须将处理程序附加到每个对象(前提是这些对象实现INotifyPropertyChanged)
实现基本上如下所示:
var collection = GetData();
collection.CollectionChanged += OnCollectionChanged;
...
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
AddPropertyChanged(e.NewItems);
break;
case NotifyCollectionChangedAction.Remove:
RemovePropertyChanged(e.OldItems);
break;
case NotifyCollectionChangedAction.Replace:
case NotifyCollectionChangedAction.Reset:
RemovePropertyChanged(e.OldItems);
AddPropertyChanged(e.NewItems);
break;
}
...
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
...
}
private void AddPropertyChanged(IEnumerable items)
{
if (items != null)
{
foreach (var obj in items.OfType<INotifyPropertyChanged>())
{
obj.PropertyChanged += OnPropertyChanged;
}
}
}
private void RemovePropertyChanged(IEnumerable items)
{
if (items != null)
{
foreach (var obj in items.OfType<INotifyPropertyChanged>())
{
obj.PropertyChanged -= OnPropertyChanged;
}
}
}
var collection=GetData();
collection.CollectionChanged+=OnCollectionChanged;
...
CollectionChanged的私有void(对象发送方,NotifyCollectionChangedEventArgs e)
{
开关(电动)
{
案例NotifyCollectionChangedAction。添加:
AddPropertyChanged(如新项目);
打破
案例NotifyCollectionChangedAction。删除:
移除已更改的财产(如旧物品);
打破
案例通知收集更改操作。替换:
案例通知CollectionChangedAction.Reset:
移除已更改的财产(如旧物品);
AddPropertyChanged(如新项目);
打破
}
...
}
私有void OnPropertyChanged(对象发送方,PropertyChangedEventArgs e)
{
...
}
私有void AddPropertyChanged(IEnumerable items)
{
如果(项!=null)
{
foreach(items.OfType()中的var obj)
{
obj.PropertyChanged+=OnPropertyChanged;
}
}
}
私有void RemovePropertyChanged(IEnumerable items)
{
如果(项!=null)
{
foreach(items.OfType()中的var obj)
{
obj.PropertyChanged-=OnPropertyChanged;
}
}
}
为了详细说明克莱门斯的上述回答,下面是使用这些事件(在集合和包含的项目上)实现IsDirty标志的简单方法,如您所述:
public class DirtyCollection<T> : ObservableCollection<T> where T : INotifyPropertyChanged
{
private bool isDirty = false;
public bool IsDirty
{
get { return this.isDirty; }
}
public void Clean()
{
this.isDirty = false;
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
// We aren't concerned with how the collection changed, just that it did.
this.isDirty = true;
// But we do need to add the handlers to detect property changes on each item.
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
this.AddPropertyChanged(e.NewItems);
break;
case NotifyCollectionChangedAction.Remove:
this.RemovePropertyChanged(e.OldItems);
break;
case NotifyCollectionChangedAction.Replace:
case NotifyCollectionChangedAction.Reset:
this.RemovePropertyChanged(e.OldItems);
this.AddPropertyChanged(e.NewItems);
break;
}
base.OnCollectionChanged(e);
}
private void AddPropertyChanged(IEnumerable items)
{
if (items != null)
{
foreach (var obj in items.OfType<INotifyPropertyChanged>())
{
obj.PropertyChanged += OnItemPropertyChanged;
}
}
}
private void RemovePropertyChanged(IEnumerable items)
{
if (items != null)
{
foreach (var obj in items.OfType<INotifyPropertyChanged>())
{
obj.PropertyChanged -= OnItemPropertyChanged;
}
}
}
private void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// A property of a contained item has changed.
this.isDirty = true;
}
}
public类DirtyCollection:ObservableCollection,其中T:INotifyPropertyChanged
{
private bool isDirty=false;
公共图书馆
{
获取{返回this.isDirty;}
}
公共空间清洁()
{
this.isDirty=false;
}
CollectionChanged上的受保护覆盖无效(NotifyCollectionChangedEventArgs e)
{
//我们不关心收藏的变化,只关心它的变化。
this.isDirty=true;
//但我们确实需要添加处理程序来检测每个项目上的属性更改。
开关(电动)
{
案例NotifyCollectionChangedAction。添加:
此.AddPropertyChanged(如NewItems);
打破
案例NotifyCollectionChangedAction。删除:
此。移除已更改的属性(如旧项目);
打破
案例通知收集更改操作。替换:
案例通知CollectionChangedAction.Reset:
此。移除已更改的属性(如旧项目);
此.AddPropertyChanged(如NewItems);
打破
}
基础。变更的集合(e);
}
私有void AddPropertyChanged(IEnumerable items)
{
如果(项!=null)
{
foreach(items.OfType()中的var obj)
{
obj.PropertyChanged+=ONTEMPROPERTYCHANGED;
}
}
}
私有void RemovePropertyChanged(IEnumerable items)
{
如果(项!=null)
{
foreach(items.OfType()中的var obj)
{
obj.PropertyChanged-=ONTEMPROPERTYCHANGED;
}
}
}
私有void OnItemPropertyChanged(对象发送方,PropertyChangedEventArgs e)
{
//所包含项的属性已更改。
this.isDirty=true;
}
}
代码应该是相当自解释的
当然,您可以删除“where T:INotifyPropertyChanged”以允许未实现该接口的对象