Wpf 检测是否修改了ObservableCollection

Wpf 检测是否修改了ObservableCollection,wpf,observablecollection,Wpf,Observablecollection,我在DockPanel中嵌套了一个DataGrid。DockPanel用作数据上下文: DockPanel1.DataContext = GetData(); GetData()方法返回一个ObservableCollection 可以在DataGrid以及DockPanel中嵌套的几个文本框中修改ObservableCollection。我还使用DataView浏览集合 我想检测集合是否已被修改,并在用户试图关闭应用程序而不保存数据时发出警告 是否有我可以使用的内置机制(集合或视图上的一种“

我在DockPanel中嵌套了一个DataGrid。DockPanel用作数据上下文:

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”以允许未实现该接口的对象