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 <=>

È stato utile?

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 /

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top