我将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可以执行此操作的唯一方法是,如果子集合的内容在绑定之间缓存。

这里发生了什么?我错过了什么???

有帮助吗?

解决方案

我找到了解决方法。它有点糟糕。

我可以将Children集合包装在BindingList中:

public IBindingList BindableChildren
{
    get
    {
        return new BindingList<Item>(Children);
    }
}

然后修改我的RemoveChild方法:

this.Children.Remove(arg);
SendPropertyChanged("BindableChildren");

这会导致UI立即更新列表并停止显示缓存行为。

问题仍然存在: WTF?还有其他方法吗?

其他提示

我不确定这一点,但也许ItemsControl正在侦听来自IBindingListINotifyCollectionChanged而不是INotifyPropertyChanged的事件。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top