【问题标题】:INotifyPropertyChanged bubbling in class hierarchy类层次结构中的 INotifyPropertyChanged 冒泡
【发布时间】:2016-07-21 16:46:41
【问题描述】:

假设,我有以下类层次结构:

public NestedClass : INotifyPropertyChanged {
    string prop1;

    public String  Prop1 {
        get { return prop1; }
        set {
            prop1 = value;
            OnPropertyChanged("Prop1");
        }
    }

    void OnPropertyChanged(String name) {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

public Class1 : INotifyPropertyChanged {
    ObservableCollection<NestedClass> collection;

    public Class1() {
        collection = new ObservableCollection<NestedClass>();
    }

    public ObservableCollection<NestedClass>  Collection {
        get { return collection; }
        set {
            if (collection != null) {
                collection.CollectionChanged -= childOnCollectionChanged;
            }
            collection = value;
            if (collection != null) {
                collection.CollectionChanged += childOnCollectionChanged;
            }
        }
    }

    void childOnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e) {
        switch (e.Action) {
            case NotifyCollectionChangedAction.Add:
                ((INotifyPropertyChanged)e.NewItems[0]).PropertyChanged += childOnPropertyChanged;
                break;
            case NotifyCollectionChangedAction.Remove:
                ((INotifyPropertyChanged)e.OldItems[0]).PropertyChanged -= childOnPropertyChanged;
                break;
            case NotifyCollectionChangedAction.Reset:
                if (e.OldItems == null) { break; }
                foreach (INotifyPropertyChanged itemToRemove in e.OldItems) {
                    itemToRemove.PropertyChanged -= childOnPropertyChanged;
                }
                break;
        }
    }
    void childOnPropertyChanged(Object sender, PropertyChangedEventArgs e) {
        OnPropertyChanged("nested");
    }

    void OnPropertyChanged(String name) {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

有一个类Class1,它包含一些属性和几个不同类的集合。所有集合的定义与 NestedClass 的集合相同。它们已正确绑定到 UI,我在那里没有问题。

Class1 对象和嵌套对象/集合可以在运行时创建,也可以由 XML 反序列化器生成。为了正确处理反序列化集合,我必须在分配集合时订阅每个集合项的INotifyPropertyChanged 事件。

我的目标是处理Class1NestedClass 的所有项目的所有更改,以获取数据已更改的信息(并将此信息传递给其父级)。

问题是我有多个嵌套集合,它们通知父类Class1,它成功地将事件冒泡到其父类。但是,一个集合通知父 Class1 有关更改,但 Class1 中的 handler 为 null,因为结果 Class1 不会将事件冒泡到其父类(此处未显示为无关紧要)。我通过调试器但无法找到问题所在。当其他嵌套集合调用父级的OnPropertyChanged 时,handler 不为空,一切正常。

编辑:仅当 XML 反序列化器生成 Class1NestedClass 对象时才会出现此问题。

我在 SO 上阅读了很多类似的帖子,但大多数都是关于视图中的无效 DataContext,这不是我的情况(我相信)。我还可以检查什么来找到问题的根源?

【问题讨论】:

  • 我怀疑它会对您有所帮助,但您可能需要考虑切换到 BindingList&lt;T&gt; 而不是 ObserveableCollection&lt;T&gt;,它已经内置了您在 childOnCollectionChanged 中执行的逻辑。只需确保 RaiseListChangedEvents 设置为 true 并且 ListChanged 事件将在任何成员之一引发其 PropertyChanged 事件时使用 args.ListChangedType == ListChangedType.ItemChanged 引发
  • 感谢提示!我会详细阅读它。但是有人声称 BindingList 在 WPF 中没有得到适当的支持:stackoverflow.com/a/4284904/3997611
  • BindingList 对于 WPF 绑定是不必要的(您的解决方案也是如此)。当您将DataSource="{Binding Path=InstanceOfClass1.Collection}" 作为列表或表格数据源执行时,在行级别上您有Text="{Binding Path=Prop1}" 各个行会自动连接到集合中的每一行,您不需要通过冒泡来“帮助它”上绑定。 BindingLists 在 WPF 中工作正常,它们没有错误,只是它们不是必需的并且会引入开销。
  • 致downvoter:这个问题有什么问题?
  • 一个友好的提示也可以解决您的问题:永远不要让您的 ObservableCollection 公开设置。如果整个集合是新设置的,它会破坏视图中的绑定,因为视图的侦听器仍然订阅旧集合。请改用.Clear(),然后添加项目。这可能会让您在序列化方面遇到困难,但这是值得的。另外,请投赞成票。这些天来有奇怪的人

标签: c# wpf event-bubbling


【解决方案1】:

您可能需要考虑切换到BindingList&lt;T&gt; 而不是ObserveableCollection&lt;T&gt;,它已经内置了您在childOnCollectionChanged 中执行的逻辑。只需确保将RaiseListChangedEvents 设置为true,并且只要其中一名成员引发PropertyChanged 事件,ListChanged 就会引发args.ListChangedType == ListChangedType.ItemChanged 事件。

【讨论】:

  • 虽然BindingList 增加了额外的开销(我可以接受,因为集合只包含十几个项目),这正是我需要的,因为我也需要收听集合项目的变化(不仅仅是集合变化)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多