我将ItemsControl绑定到WPF应用程序中的EntitySet。然而,它没有按预期行事。 ItemsControl的行为好像是缓存绑定之间的EntitySet的内容!
以下是精简代码:
实体:
public partial class Item : INotifyPropertyChanging, INotifyPropertyChanged
{
private EntitySet<Item> _Children;
public EntitySet<Item> Children {get{return _children;}}
/*...*/
}
我的部分课程:
public partial class Item
{
public void RemoveChild(Item child)
{
Children.Remove(child);
// this finds PropertyChanged; defined in the Entity class
SendPropertyChanged("Children");
}
}
用户界面:
<ItemsControl
Name="ItemChildren"
Background="CornflowerBlue"
ItemsSource="{Binding Children}">
<ItemsControl.ItemTemplate>
<DataTemplate
DataType="{x:Type d:Item}">
<DockPanel>
<TextBlock
Text="{Binding Name}/>
</DockPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
演示行为的代码(假设&gt; 2个项目,每个项目都有一个孩子):
this.ScrewyItem = Db.Items.First();
this.DataContext = ScrewyItem;
return;
稍后,我从实体中删除了孩子:
ScrewyItem.RemoveChild(ScrewyItem.Children.First());
return;
此代码运行后,UI不会更新,并且Item显示为包含所有子项。请注意,此方法调用NotifyPropertyChanged,因此绑定应更新!
稍后,我们从UI绑定中删除此项目:
this.DataContext = Db.Items.Last(); //different item
return;
然后再将其绑定到UI
this.DataContext = ScrewyItem;
您会认为此时至少UI会显示正确的子列表。 然而, 它显示了最初显示的相同子项列表!
更奇怪的是,如果我在我的儿童访问器上放置一个断点,我可以看到当我重新绑定到用户界面时访问该列表 和 该列表不包含我删除的孩子。
我可以看到UI可以执行此操作的唯一方法是,如果子集合的内容在绑定之间缓存。
这里发生了什么?我错过了什么???
答案 0 :(得分:0)
我找到了解决方法。它有点糟糕。
我可以将Children集合包装在BindingList中:
public IBindingList BindableChildren
{
get
{
return new BindingList<Item>(Children);
}
}
然后修改我的RemoveChild方法:
this.Children.Remove(arg);
SendPropertyChanged("BindableChildren");
这会导致UI立即更新列表并停止显示缓存行为。
问题仍然存在: WTF?和还有其他方法吗?
答案 1 :(得分:0)
我不确定这一点,但也许ItemsControl
正在收听来自IBindingList
或INotifyCollectionChanged
而不是INotifyPropertyChanged
的事件。