WPF: ein Element zu einer Databound-Sammlung hinzufügen (a Abhängigkeitseigenschaft)
-
21-08-2019 - |
Frage
Ich habe diese DependencyProperty
, die eine Einheit mit einer Eigenschaft enthält, die eine Sammlung (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); }
}
Es binded wird in xaml
wie so:
<ItemsControl ItemsSource="{Binding ShoutBox.Entries}">
.
.
</ItemsControl>
Als ich es das erste Mal binden, es funktioniert wie erwartet, aber es gibt Zeiten, wenn ich Elemente in die Sammlung hinzufügen muß (mit einem Verfahren, das in der gleichen Kontrolle ist), wie solche:
public void AddNewEntry(ShoutBoxEntry newEntry)
{
Dispatcher.Invoke(new Action(() =>{
ShoutBox.Entries.Add(newEntry); //Adding directly the the Dependency property
}));
}
Das Problem ist, dass, wenn ich ein neues Element mit dem obigen Verfahren hinzufügen, wird das Element nicht in den ItemsControl
angezeigt wird.
Meine Frage ist, warum nicht das neue Element, das ich das Hinzufügen bin nicht in den ItemsControl
angezeigt wird,
[Bearbeiten]
Entries
( ShoutBox.Entries ) vom Typ List<ShoutBoxEntry>
Lösung
Was ist die Art der Einträge? Es muss entweder ObservableCollection oder implementieren ICollectionChanged sein. Ansonsten ist die Bindung nicht weiß, dass ein neues Element hinzugefügt worden ist.
Andere Tipps
Die Änderung der Einträge sollte in der Tat das Problem lösen ... Wenn Sie den expliziten Aufruf Dispatcher.Invoke vermeiden wollen, schrieb ich eine Sammlung, die die Collection und Property Ereignisse auf dem Thread aufwirft, die die Sammlung erstellt:
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);
}
}
Weitere Informationen finden Sie hier: http://www.thomaslevesque.com / 2009/04/17 / wpf-binding-to-an-asynchron-Sammlung /