WPF: Adicionando um elemento a uma coleção de ligação de dados (a propriedade de dependência)
-
21-08-2019 - |
Pergunta
Eu tenho essa DependencyProperty
que detém uma entidade com uma propriedade que é uma coleção (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); }
}
Está a ser binded em xaml
como tal:
<ItemsControl ItemsSource="{Binding ShoutBox.Entries}">
.
.
</ItemsControl>
Quando eu ligá-la pela primeira vez, ele funciona como esperado, mas há momentos em que eu preciso adicionar itens à coleção (com um método que está na mesma controle), como tal:
public void AddNewEntry(ShoutBoxEntry newEntry)
{
Dispatcher.Invoke(new Action(() =>{
ShoutBox.Entries.Add(newEntry); //Adding directly the the Dependency property
}));
}
O problema é que quando eu adicionar um novo elemento com o método acima, o item não está sendo exibido no ItemsControl
.
A minha pergunta é, por que não é o novo elemento que estou adicionando não está sendo exibido no ItemsControl
?
[Edit]
Entries
( ShoutBox.Entries ) é do tipo List<ShoutBoxEntry>
Solução
O que é o tipo de inscritos? Ele quer precisa ser ObservableCollection ou implementar ICollectionChanged. Caso contrário, a ligação não sabe que um novo item foi adicionado.
Outras dicas
A alteração do tipo de inscritos deve realmente resolver o problema ... Se você quiser evitar a chamada explícita para Dispatcher.Invoke, eu escrevi uma coleção que gera os eventos CollectionChanged e PropertyChanged no segmento que criou a coleção:
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);
}
}
Mais detalhes podem ser encontrados aqui: http://www.thomaslevesque.com / 2009/04/17 / WPF de ligação-a-um-assíncrona de coleta /