WPF: aggiunta di un elemento a una raccolta di database (una proprietà di dipendenza)
-
21-08-2019 - |
Domanda
Ho questo DependencyProperty
che detiene un'entità con una proprietà che è una raccolta (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); }
}
Viene associato in xaml
in questo modo:
<ItemsControl ItemsSource="{Binding ShoutBox.Entries}">
.
.
</ItemsControl>
Quando lo rilevo la prima volta, funziona come previsto ma ci sono volte in cui devo aggiungere elementi alla raccolta (con un metodo che ha lo stesso controllo), come tale:
public void AddNewEntry(ShoutBoxEntry newEntry)
{
Dispatcher.Invoke(new Action(() =>{
ShoutBox.Entries.Add(newEntry); //Adding directly the the Dependency property
}));
}
Il problema è che quando aggiungo un nuovo elemento con il metodo sopra, l'elemento non viene visualizzato in ItemsControl
.
La mia domanda è: perché il nuovo elemento che sto aggiungendo non viene visualizzato in Entries
?
[Edit]
List<ShoutBoxEntry>
( ShoutBox.Entries ) è di tipo <=>
Soluzione
Qual è il tipo di voci? Deve essere ObservableCollection o implementare ICollectionChanged. Altrimenti l'associazione non sa che è stato aggiunto un nuovo oggetto.
Altri suggerimenti
La modifica del tipo di voci dovrebbe effettivamente risolvere il problema ... Se vuoi evitare la chiamata esplicita a Dispatcher.Invoke, ho scritto una raccolta che genera gli eventi CollectionChanged e PropertyChanged sul thread che ha creato la raccolta:
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);
}
}
Maggiori dettagli sono disponibili qui: http://www.thomaslevesque.com / 2009/04/17 / WPF-binding-a-un-asincrono-raccolta /