【发布时间】: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 事件。
我的目标是处理Class1 中NestedClass 的所有项目的所有更改,以获取数据已更改的信息(并将此信息传递给其父级)。
问题是我有多个嵌套集合,它们通知父类Class1,它成功地将事件冒泡到其父类。但是,一个集合通知父 Class1 有关更改,但 Class1 中的 handler 为 null,因为结果 Class1 不会将事件冒泡到其父类(此处未显示为无关紧要)。我通过调试器但无法找到问题所在。当其他嵌套集合调用父级的OnPropertyChanged 时,handler 不为空,一切正常。
编辑:仅当 XML 反序列化器生成 Class1 和 NestedClass 对象时才会出现此问题。
我在 SO 上阅读了很多类似的帖子,但大多数都是关于视图中的无效 DataContext,这不是我的情况(我相信)。我还可以检查什么来找到问题的根源?
【问题讨论】:
-
我怀疑它会对您有所帮助,但您可能需要考虑切换到
BindingList<T>而不是ObserveableCollection<T>,它已经内置了您在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