WPF:データバインドされたコレクション (依存関係プロパティ) への要素の追加

StackOverflow https://stackoverflow.com/questions/845636

質問

これを持っています 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.エントリー) のタイプです List<ShoutBoxEntry>

役に立ちましたか?

解決

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

他のヒント

エントリのタイプを変更すると、実際に問題が解決されるはずです...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/

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top