1

DependencyPropertyコレクション( )であるプロパティを持つエンティティを保持するこれがありますShoutBox.Entities

public static readonly DependencyProperty ShoutBoxProperty = DependencyProperty.Register("ShoutBox",typeof (ShoutBox),typeof (ShoutBoxViewerControl));

public ShoutBox ShoutBox
{
    get { return (ShoutBox) GetValue(ShoutBoxProperty); }
    set { SetValue(ShoutBoxProperty, value); }
}

xaml次のようにバインドされています。

<ItemsControl ItemsSource="{Binding ShoutBox.Entries}">
.
.
</ItemsControl>

初めてバインドすると、期待どおりに動作しますが、次のように (同じコントロール内にあるメソッドを使用して) コレクションに項目を追加する必要がある場合があります。

public void AddNewEntry(ShoutBoxEntry newEntry)
{
    Dispatcher.Invoke(new Action(() =>{
        ShoutBox.Entries.Add(newEntry); //Adding directly the the Dependency property
    }));
}

問題は、上記の方法で新しい要素を追加すると、アイテムが に表示されないことItemsControlです。


私の質問は、追加している新しい要素がに表示されないのはなぜItemsControlですか?


[編集]

Entries( ShoutBox.Entries ) はタイプですList<ShoutBoxEntry>

4

2 に答える 2

3

エントリーの種類は?ObservableCollection であるか、ICollectionChanged を実装する必要があります。そうしないと、バインディングは新しいアイテムが追加されたことを認識しません。

于 2009-05-10T16:50:44.257 に答える
0

Entries のタイプを変更すると、実際に問題が解決するはずです... Dispatcher.Invoke への明示的な呼び出しを避けたい場合は、コレクションを作成したスレッドで CollectionChanged および PropertyChanged イベントを発生させるコレクションを作成しました。

public class AsyncObservableCollection<T> : ObservableCollection<T>
{
    private SynchronizationContext _synchronizationContext = SynchronizationContext.Current;

    public AsyncObservableCollection()
    {
    }

    public AsyncObservableCollection(IEnumerable<T> list)
        : base(list)
    {
    }

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (SynchronizationContext.Current == _synchronizationContext)
        {
            // Execute the CollectionChanged event on the current thread
            RaiseCollectionChanged(e);
        }
        else
        {
            // Post the CollectionChanged event on the creator thread
            _synchronizationContext.Post(RaiseCollectionChanged, e);
        }
    }

    private void RaiseCollectionChanged(object param)
    {
        // We are in the creator thread, call the base implementation directly
        base.OnCollectionChanged((NotifyCollectionChangedEventArgs)param);
    }

    protected override void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (SynchronizationContext.Current == _synchronizationContext)
        {
            // Execute the PropertyChanged event on the current thread
            RaisePropertyChanged(e);
        }
        else
        {
            // Post the PropertyChanged event on the creator thread
            _synchronizationContext.Post(RaisePropertyChanged, e);
        }
    }

    private void RaisePropertyChanged(object param)
    {
        // We are in the creator thread, call the base implementation directly
        base.OnPropertyChanged((PropertyChangedEventArgs)param);
    }
}

詳細については、 http ://www.thomaslevesque.com/2009/04/17/wpf-binding-to-an-asynchronous-collection/ を参照してください。

于 2009-05-10T22:58:52.810 に答える