C# 如何通知可观察集合中项目的属性已更改?

C# 如何通知可观察集合中项目的属性已更改?,c#,wpf,xaml,observablecollection,inotifypropertychanged,C#,Wpf,Xaml,Observablecollection,Inotifypropertychanged,好的,我在XAML文件中有一个ItemsControl,它绑定到一个ObservableCollection。ObservableCollection是在一个视图模型类(我们称之为ViewModelA)上找到的,ObservableCollection中的每个项都是另一个视图模型类(我们称之为ViewModelB)的实例 ViewModelA上有一个属性,如果更改,将间接更改ViewModelB类的许多实例中的属性值。换句话说,它不会直接转到ViewModelB并设置其属性,从而导致INotif

好的,我在XAML文件中有一个ItemsControl,它绑定到一个ObservableCollection。ObservableCollection是在一个视图模型类(我们称之为ViewModelA)上找到的,ObservableCollection中的每个项都是另一个视图模型类(我们称之为ViewModelB)的实例

ViewModelA上有一个属性,如果更改,将间接更改ViewModelB类的许多实例中的属性值。换句话说,它不会直接转到ViewModelB并设置其属性,从而导致INotifyPropertyChange调用,而是转到模型,在模型中设置一些属性,并且模型中的更改会影响ViewModelB应该显示视图的内容


如何通知视图ViewModelB中的某些内容已更改?

您应该能够告诉视图集合已更改,并反过来触发它重新绑定到整个集合(这将更新视图)


如果您的模型实现了
INotifyPropertyChanged
,另一个选项是让您的
ViewModelB
类侦听其包装模型上的更改,并根据需要引发属性更改事件。

为了解决这个问题,我创建了一个名为VeryObservableCollection的类。对于您添加的每个对象,它将对象的NotifyPropertyChanged事件挂接到触发CollectionChanged事件的处理程序。对于删除的每个对象,它都会删除处理程序。非常简单,会给你你想要的。部分代码:

public class VeryObservableCollection<T> : ObservableCollection<T>

/// <summary>
/// Override for setting item
/// </summary>
/// <param name="index">Index</param>
/// <param name="item">Item</param>
protected override void SetItem(int index, T item)
{
    try
    {
        INotifyPropertyChanged propOld = Items[index] as INotifyPropertyChanged;
        if (propOld != null)
            propOld.PropertyChanged -= new PropertyChangedEventHandler(Affecting_PropertyChanged);
    }
    catch (Exception ex)
    {
        Exception ex2 = ex.InnerException;
    }
    INotifyPropertyChanged propNew = item as INotifyPropertyChanged;
    if (propNew != null)
        propNew.PropertyChanged += new PropertyChangedEventHandler(Affecting_PropertyChanged);

    base.SetItem(index, item);
}
public类veryoobservableCollection:ObservableCollection
/// 
///设置项的覆盖
/// 
///索引
///项目
受保护的覆盖无效集合项(整数索引,T项)
{
尝试
{
INotifyPropertyChanged propOld=作为INotifyPropertyChanged的项目[索引];
if(propOld!=null)
propOld.PropertyChanged-=新的PropertyChangedEventHandler(影响_PropertyChanged);
}
捕获(例外情况除外)
{
异常ex2=ex.InnerException;
}
INotifyPropertyChanged propNew=项目作为INotifyPropertyChanged;
if(propNew!=null)
propNew.PropertyChanged+=新PropertyChangedEventHandler(影响_PropertyChanged);
base.SetItem(索引,项);
}

如果模型中的更改将更改ViewModelB的某些属性,并且这些属性已向UI发出更改通知(即ViewModleB正在实现INotifyPropertyChanged),则更改将立即反映在UI中


因此,如果您有另一个viewmodelB的ObservableCollection,则不需要为该viewmodelB的propertychanged连接事件。根据我的理解,无论谁更改viewmodelB的属性(模型类或其他任何人),如果属性有更改通知,视图都将自动更新

理想情况下,你可以像里德·科佩所说的那样。。。在模型上实现INotifyPropertyChanged,并让ViewModelB侦听这些事件。然后,无论更新发生在何处,ViewModelB都将拾取更改

但是,在某些情况下,模型不(或不能)实现INotifyPropertyChanged。在这种情况下,您可能需要考虑使用事件聚合器模式在ViewModelA和VIEWMODEB实例之间传递消息。p> 在这种情况下,您可以从ViewModelA发布“模型更改”消息。ViewModelB实例将订阅此消息,并在发布消息时通知每个实例。然后ViewModelB可以引发适当的PropertyChanged事件,以告诉UI发生了什么变化

您可以在许多框架中找到有关事件聚合器的更多信息,包括


+1;您的答案比问题更清楚,因此我将重申一般情况:通知视图更改的两种方法是
INotifyCollectionChanged
INotifyPropertyChanged
。但是,如果您的视图模型是相互依赖的,那么在视图模型中也使用这些接口,并根据需要弹出通知是非常自然的。这里的关键是集合本身没有改变,因此INotifyCollectionChanged对我没有好处。但是,我可以在我的模型类上实现INotifyPropertyChanged,所以看起来它可以工作。谢谢你的帮助!