如何让父母阶层了解其子女的变化?

iXe*_*Xed 8 c# wpf binding parent-child inotifypropertychanged

这是一个示例代码:

public class MyParent : INotifyPropertyChanged
{
    List<MyChild> MyChildren;

    public bool IsChanged
    {
        get
        {
            foreach (var child in MyChildren)
            {
                if (child.IsChanged) return true;
            }
            return false;
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;
    private void RaiseChanged(string propName)
    {
        if (PropertyChanged != null)
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propName));
    }
}

public class MyChild : INotifyPropertyChanged
{
    private int _Value;
    public int Value
    {
        get
        {
            return _Value;
        }
        set
        {
            if (_Value == value)
                return;
            _Value = value;
            RaiseChanged("Value");
            RaiseChanged("IsChanged");
        }
    }
    private int _DefaultValue;
    public int DefaultValue
    {
        get
        {
            return _DefaultValue;
        }
        set
        {
            if (_DefaultValue == value)
                return;
            _DefaultValue = value;
            RaiseChanged("DefaultValue");
            RaiseChanged("IsChanged");
        }
    }

    public bool IsChanged
    {
        get
        {
            return (Value != DefaultValue);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void RaiseChanged(string propName)
    {
        if (PropertyChanged != null)
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propName));
    }
}
Run Code Online (Sandbox Code Playgroud)

假设我现在有两个类的实例,一个是myParent,另一个是myChild.我有两个可视元素,每个元素都有一个绑定到我的实例的IsChnaged属性的属性; ElementA绑定到myParent.IsChanged,ElementB绑定到myChild.IsChanged.

当myChild.Value与其默认值不同时,myChild.IsChanged将设置为true,并相应地更新ElementB.

我需要的是当任何一个myParent子节点(这里只有一个)将其IsChanged值设置为true时,将其自己的(父节点)IsChanged值设置为true,并相应地更新其对应元素(此处为ElementA).

myParent.IsChanged只读一次(当设置绑定时)并且它的子节点没有变化.我应该把MyParent的RaiseChanged("IsChanged")放在哪里?如果孩子的孩子改变了,我怎么能让他们知道呢?

提前致谢

dle*_*lev 13

INotifyPropertyChanged已经为你提供了这个机制:PropertyChanged事件.让父进程为其子进程添加一个处理程序PropertyChanged,然后在该处理程序调用中添加一个处理程序RaiseChanged("IsChanged");

此外,您可能希望将INotifyPropertyChanged实现放在基类中,并使您的(似乎是)ViewModels继承自该类.当然,这个选项不需要,但它会使代码更清洁.

更新:在父对象中:

// This list tracks the handlers, so you can
// remove them if you're no longer interested in receiving notifications.
//  It can be ommitted if you prefer.
List<EventHandler<PropertyChangedEventArgs>> changedHandlers =
    new List<EventHandler<PropertyChangedEventArgs>>();

// Call this method to add children to the parent
public void AddChild(MyChild newChild)
{
    // Omitted: error checking, and ensuring newChild isn't already in the list
    this.MyChildren.Add(newChild);
    EventHandler<PropertyChangedEventArgs> eh =
        new EventHandler<PropertyChangedEventArgs>(ChildChanged);
    newChild.PropertyChanged += eh;
    this.changedHandlers.Add(eh);
}

public void ChildChanged(object sender, PropertyChangedEventArgs e)
{
    MyChild child = sender as MyChild;
    if (this.MyChildren.Contains(child))
    {
        RaiseChanged("IsChanged");
    }
}
Run Code Online (Sandbox Code Playgroud)

您实际上不必向子类添加任何内容,因为它在更改时已经引发了正确的事件.