如何在集合中传播对象的属性更改通知

Err*_*ror 5 c# event-handling inotifypropertychanged windows-forms-designer

可以说我有这样的课程

public class R
{
    protected string name;
    protected List<S> listOfObjectS;
}

public class S
{
    private string name, ID;
    private A objectA;
}

public class A
{
    private string name;
    private int count;
}
Run Code Online (Sandbox Code Playgroud)

如果用户打开了两个视图,一个显示实例,R另一个允许用户修改实例A,我需要R在用户更改任何实例时更改视图A.

如果用户更改了实例的属性A,那么传播该更改的最佳方式是什么(通过实例S),以便所有实例R显示新的状态A?

Dav*_*rtz 9

编辑:由于标签显示您已经知道,因此对此问题进行检修更具体INotifyPropertyChanged.

你需要INotifyPropertyChanged在课堂上A和课堂上实现S.这样做objectA只能通过一个属性进行设置,该属性会PropertyChanged在更改属性时在S上引发事件A.例:

public class A : INotifyPropertyChanged
{
    private string name;
    public string Name
    {
        get { return name; }
        set { name = value; OnPropertyChanged("Name"); }
    }

    private int count;

    public int Count
    {
        get { return count; } 
        set { count = value; OnPropertyChanged("Count"); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
Run Code Online (Sandbox Code Playgroud)

......和班级S......

public class S : INotifyPropertyChanged
{
    private string name, ID;
    private A objectA;

    public A ObjectA
    {
        get { return objectA; }
        set
        {
            var old = objectA;
            objectA = value;

            // Remove the event subscription from the old instance.
            if (old != null) old.PropertyChanged -= objectA_PropertyChanged;

            // Add the event subscription to the new instance.
            if (objectA != null) objectA.PropertyChanged += objectA_PropertyChanged;

            OnPropertyChanged("ObjectA");
        }
    }

    void objectA_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        // Propagate the change to any listeners. Prefix with ObjectA so listeners can tell the difference.
        OnPropertyChanged("ObjectA." + e.PropertyName);
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
Run Code Online (Sandbox Code Playgroud)

对于类R,使用ObservableCollection<S>而不是List<S>,并订阅它的CollectionChanged事件,并监视何时添加或删除对象listOfObjectS.当它们被添加,订阅S的PropertyChanged事件.然后更新了R视图.例:

public class R
{
    protected string name;
    protected System.Collections.ObjectModel.ObservableCollection<S> ListOfObjectS { get; private set; }

    public R()
    {
        // Use ObservableCollection instead.
        ListOfObjectS = new ObservableCollection<S>();

        // Subscribe to all changes to the collection.
        ListOfObjectS.CollectionChanged += listOfObjectS_CollectionChanged;
    }

    void listOfObjectS_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == NotifyCollectionChangedAction.Remove)
        {
            // When items are removed, unsubscribe from property change notifications.
            var oldItems = (e.OldItems ?? new INotifyPropertyChanged[0]).OfType<INotifyPropertyChanged>();
            foreach (var item in oldItems)
                item.PropertyChanged -= item_PropertyChanged;
        }

        // When item(s) are added, subscribe to property notifications.
        if (e.Action == NotifyCollectionChangedAction.Add)
        {
            var newItems = (e.NewItems ?? new INotifyPropertyChanged[0]).OfType<INotifyPropertyChanged>();
            foreach (var item in newItems)
                item.PropertyChanged += item_PropertyChanged;
        }

        // NOTE: I'm not handling NotifyCollectionChangedAction.Reset.
        // You'll want to look into when this event is raised and handle it
        // in a special fashion.
    }

    void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName.StartsWith("ObjectA."))
        {
            // Refresh any dependent views, forms, controls, whatever...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)