WPF:データバインドされたコレクション (依存関係プロパティ) への要素の追加
-
21-08-2019 - |
質問
これを持っています 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/
所属していません StackOverflow