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");
    }
}

UI:

<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つ以上のアイテムを想定し、それぞれに1つの子があります)。

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

これについてはよくわかりませんが、おそらくはItemsControlからのイベントをリッスンしているIBindingListかどうかはわかりINotifyCollectionChangedませんINotifyPropertyChanged

于 2009-08-01T21:39:02.703 に答える
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 に答える