2012-10-14 7 views
7

Ecco quello che ho - un ListBox con un'ItemsSource impostata su un ObservableCollection<T> - dove T è la mia classe personalizzata che rappresenta un file, che contiene solo 2 DependencyProperties: Nome file e ThumbnailPath. - La listbox ha anche un DataTemplate personalizzato definito, al fine di visualizzare con piacere un'immagine e il nome del file sotto di esso.asincrono aggiungendo ObservableCollection (o in alternativa)

Lo scopo della casella di riepilogo è visualizzare i file video nella cartella corrente (selezionata in un TreeView), con miniature (generate in modo asincrono, non facenti parte di questo problema).

Così quando cambio la cartella in TreeView, ObservableCollection viene cancellata e riempita di nuovo, che si riflette automaticamente negli oggetti ListBox.

Ecco il problema: l'interfaccia utente non risponde e sono necessari alcuni secondi per l'aggiornamento. Ancora una volta, le miniature non hanno significato qui (ho provato a disabilitarle). Penso che ciò che richiede più tempo sia la costruzione di 50-100 istanze della mia classe personalizzata, e la loro rappresentazione visiva - deve inizializzare un oggetto Immagine per ognuno. Ma è solo una mia ipotesi - potresti confermare o escludere la possibilità?

Sto cominciando a pensare ObservableCollection non posso la strada da percorrere qui, dal momento che da quello che ho letto e un po 'da quello che ho provato, non c'è modo di aggiungere elementi in modo asincrono, almeno se questi elementi sono DependencyObjects. Ho provato a creare le istanze di classe con un BackgroundWorker e ad aggiungerle alla raccolta nel gestore di eventi ProgressChanged, ma genera un'eccezione (alcuni problemi di threading e dependencyobjects).

C'è qualcosa che mi manca? O dovrei stare meglio semplicemente abbandonando ObservableCollection e scrivendo un buon vecchio async per il loop per aggiungere gli elementi?

+1

Qual è il tipo di eccezione esatto e il messaggio? – Adam

+0

"È necessario creare DependencySource sullo stesso thread di DependencyObject" –

+0

E a proposito di "Binding, IsAsync = True"? –

risposta

12

Dato che il tuo ObservableCollection è associato all'interfaccia utente, viene generato sul thread dell'interfaccia utente, pertanto eventuali ulteriori aggiornamenti (eliminazione/aggiunta/cancellazione) devono trovarsi sullo stesso thread dell'interfaccia utente. Non consente aggiornamenti da un altro thread.

Tuttavia, ciò che si può fare è di creare insance della classe (o tutti in termini di tempo di funzionamento su thread in background) e una volta si è fatto, aggiungere l'oggetto in ObservableCollection utilizzando Dispatcher del thread UI come questo -

App.Current.Dispatcher.BeginInvoke((Action)delegate() 
          { 
           observableCollection.Add(instanceOfYourClass); 
          }); 

Cosa fa Dispatcher fare l'operazione sul thread associato. Quindi, l'elemento verrà sempre aggiunto sul thread dell'interfaccia utente, ma può essere creato nel thread in background.

Qui ci sono alcuni link che potrebbero farti andare - Updating from BW e un altro here

+0

Grazie, lo proverò e controllerò sicuramente l'articolo interessante, tuttavia ho provato qualcosa di simile (non riesco a trovarlo ora) senza fortuna ... Penso che abbia avuto un problema con la mia classe di essere un DependencyObject. Qualcosa come "non puoi creare un oggetto dipendente da un thread e usarlo su un altro". –

+0

Sì, i tuoi DP devono essere creati sul thread UI stesso.Nel caso in cui si desideri associarlo alla propria interfaccia utente, è necessario utilizzare i DP, ma in caso contrario, suggerirei di utilizzare semplici proprietà 'POCO' che implementano l'interfaccia' INPC'. –

+0

Voglio legarlo ... Ho bisogno della casella di riepilogo per visualizzare un elenco delle istanze di classe FILE, con il mio datatemplate personalizzato applicato. Penso che andrò con l'INPC. –

5

Con .NET 4.5 è possibile utilizzare EnableCollectionSynchronization

object lockObj = new object(); 
     BindingOperations.EnableCollectionSynchronization(yourObservableCollection, lockObj); 
Problemi correlati