如何检测我的ObservableCollection中的项是否已更改

时间:2021-10-16 00:07:21

I have a datagrid which is bound to ObservableCollection<Product>. When the grid is updated this automatically updates the Product object in my collection.

我有一个绑定到ObservableCollection 的数据网格。更新网格后,这会自动更新集合中的Product对象。

What I want to do now is to have some sort of even that is triggered when any object in the collection is updated -or- some sort of binding to the collection that will return true/false depedant on if any Product has been updated.

我现在要做的是在集合中的任何对象被更新时触发某种甚至触发 - 或者 - 某种类型的绑定到集合,如果任何产品已经更新,它将返回真/假的depedant。

The overall objective is to have a save button on my main window that is disabled if no changes have been made to my collection and enabled if changes have been made.

总体目标是在我的主窗口上有一个保存按钮,如果没有对我的集合进行任何更改,则该按钮被禁用,如果已经进行了更改,则启用该按钮。

I have read into INotifyPropertyChange but I dont see how I can use this to monitor changes on a whole collection.

我已经阅读了INotifyPropertyChange,但我没有看到我如何使用它来监控整个集合的变化。

Additionally, if I implement this interface on my Product class I dont see how my UI can monitor every product in the collection - or can it?

另外,如果我在我的Product类上实现这个接口,我不会看到我的UI如何监视集合中的每个产品 - 或者它可以吗?

4 个解决方案

#1


12  

  • Implement INotifyPropertyChanged in your Product class with notification for every property.
  • 在Product类中实现INotifyPropertyChanged,并为每个属性提供通知。
  • Implement INotifyPropertyChanged in your viewmodel.
  • 在viewmodel中实现INotifyPropertyChanged。
  • Add property IsDirty to your ViewModel (with notification through INotifyPropertyChanged.
  • 将属性IsDirty添加到ViewModel(通过INotifyPropertyChanged通知。
  • In your viewmodel, subscribe to CollectionChanged

    在您的viewmodel中,订阅CollectionChanged

    public YourViewModel()
    {
        ...
        YourCollection.CollectionChanged += YourCollection_CollectionChanged; 
        ...
    }
    
    private void YourCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs args)
    {
        if (args.OldItems != null)
            foreach(var oldItem in args.OldItems)
                oldItem.PropertyChanged -= YourItem_PropertyChanged;
    
        if (args.NewItems != null)
            foreach(var newItem in args.NewItems)
                newItem.PropertyChanged += YourItem_PropertyChanged;
    }
    
    private void Youritem_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs args)
    {
        IsDirty = true;
    }
    
  • Now you can bind to IsDirty property of your viewmodel, for example, you can bind Button.IsEnabled property directly to it.

    现在您可以绑定到viewmodel的IsDirty属性,例如,您可以将Button.IsEnabled属性直接绑定到它。

#2


1  

Just use the ObservableCollection. It has an event called CollectionChanged. If you register it, you can do what you want. Example:

只需使用ObservableCollection。它有一个名为CollectionChanged的事件。如果你注册它,你可以做你想要的。例:

ObservableCollection<string> strings = new ObservableCollection<string>();
strings.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(changed);
strings.Add("Hello");
strings[0] = "HelloHello";

And:

和:

private void changed(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs args)
{
    //You get notified here two times.
}

#3


1  

The logic needs to go in your Model (Product class). A clean approach would be to expose IsDirty property (backed by field) in your model.

逻辑需要进入您的模型(产品类)。一种干净的方法是在模型中公开IsDirty属性(由字段支持)。

And your ViewModel would have a Command binding with CanSave checking the internal collection, and return true if Any of the item in collection IsDirty=true.

并且您的ViewModel将使用CanSave的Command绑定检查内部集合,如果集合中的任何项目IsDirty = true,则返回true。

#4


0  

I think subscribing to the PropertyChanged event for each of the objects in your collection and firing this event, for example, in the setter of your objects can work.

我认为为集合中的每个对象订阅PropertyChanged事件并触发此事件,例如,在对象的setter中可以工作。

However, I think you don't need to do all this to figure out if a cell is changed in your grid. I think you can do something like what they do here instead:

但是,我认为您不需要做所有这些来确定您的网格中是否更改了单元格。我认为你可以做类似他们在这里做的事情:

http://social.msdn.microsoft.com/Forums/en/wpf/thread/81131225-90fb-40f9-a311-066952c7bc43

http://social.msdn.microsoft.com/Forums/en/wpf/thread/81131225-90fb-40f9-a311-066952c7bc43

#1


12  

  • Implement INotifyPropertyChanged in your Product class with notification for every property.
  • 在Product类中实现INotifyPropertyChanged,并为每个属性提供通知。
  • Implement INotifyPropertyChanged in your viewmodel.
  • 在viewmodel中实现INotifyPropertyChanged。
  • Add property IsDirty to your ViewModel (with notification through INotifyPropertyChanged.
  • 将属性IsDirty添加到ViewModel(通过INotifyPropertyChanged通知。
  • In your viewmodel, subscribe to CollectionChanged

    在您的viewmodel中,订阅CollectionChanged

    public YourViewModel()
    {
        ...
        YourCollection.CollectionChanged += YourCollection_CollectionChanged; 
        ...
    }
    
    private void YourCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs args)
    {
        if (args.OldItems != null)
            foreach(var oldItem in args.OldItems)
                oldItem.PropertyChanged -= YourItem_PropertyChanged;
    
        if (args.NewItems != null)
            foreach(var newItem in args.NewItems)
                newItem.PropertyChanged += YourItem_PropertyChanged;
    }
    
    private void Youritem_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs args)
    {
        IsDirty = true;
    }
    
  • Now you can bind to IsDirty property of your viewmodel, for example, you can bind Button.IsEnabled property directly to it.

    现在您可以绑定到viewmodel的IsDirty属性,例如,您可以将Button.IsEnabled属性直接绑定到它。

#2


1  

Just use the ObservableCollection. It has an event called CollectionChanged. If you register it, you can do what you want. Example:

只需使用ObservableCollection。它有一个名为CollectionChanged的事件。如果你注册它,你可以做你想要的。例:

ObservableCollection<string> strings = new ObservableCollection<string>();
strings.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(changed);
strings.Add("Hello");
strings[0] = "HelloHello";

And:

和:

private void changed(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs args)
{
    //You get notified here two times.
}

#3


1  

The logic needs to go in your Model (Product class). A clean approach would be to expose IsDirty property (backed by field) in your model.

逻辑需要进入您的模型(产品类)。一种干净的方法是在模型中公开IsDirty属性(由字段支持)。

And your ViewModel would have a Command binding with CanSave checking the internal collection, and return true if Any of the item in collection IsDirty=true.

并且您的ViewModel将使用CanSave的Command绑定检查内部集合,如果集合中的任何项目IsDirty = true,则返回true。

#4


0  

I think subscribing to the PropertyChanged event for each of the objects in your collection and firing this event, for example, in the setter of your objects can work.

我认为为集合中的每个对象订阅PropertyChanged事件并触发此事件,例如,在对象的setter中可以工作。

However, I think you don't need to do all this to figure out if a cell is changed in your grid. I think you can do something like what they do here instead:

但是,我认为您不需要做所有这些来确定您的网格中是否更改了单元格。我认为你可以做类似他们在这里做的事情:

http://social.msdn.microsoft.com/Forums/en/wpf/thread/81131225-90fb-40f9-a311-066952c7bc43

http://social.msdn.microsoft.com/Forums/en/wpf/thread/81131225-90fb-40f9-a311-066952c7bc43