0

我将 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>

演示行为的代码(假设 >2 个项目,每个项目都有一个孩子):

this.ScrewyItem = Db.Items.First();
this.DataContext = ScrewyItem;
return;

后来,我从实体中删除了孩子:

ScrewyItem.RemoveChild(ScrewyItem.Children.First());
return;

此代码运行后,UI 不会更新,并且该项目显示为具有所有子项。请注意,此方法调用 NotifyPropertyChanged,因此绑定应该更新!

稍后,我们从 UI 绑定中删除此项目:

this.DataContext = Db.Items.Last(); //different item
return;

然后稍后再次将其绑定到 UI

this.DataContext = ScrewyItem;

您会假设至少此时 UI 会显示正确的子列表。 然而,情况并非如此!它显示了与最初显示的相同的孩子列表!

更奇怪的是,如果我在 Children 访问器上放了一个断点,我可以看到当我重新绑定到 UI 时访问了该列表, 并且 该列表不包含我删除的子项。

我可以看到 UI 可以执行此操作的唯一方法是,如果 Children 集合的内容在绑定之间缓存。

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

4

2 回答 2

0

我已经找到了解决方案。这有点糟糕。

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

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

然后修改我的 RemoveChild 方法:

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

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

问题仍然存在:WTF?还有另一种方法吗?

于 2009-08-01T21:20:28.483 回答
0

我不确定这一点,但也许ItemsControl是监听来自IBindingListorINotifyCollectionChanged和 not的事件INotifyPropertyChanged

于 2009-08-01T21:39:02.703 回答