Un modo migliore per forzare l'aggiornamento di ListBox WPF associato ai dati?
-
05-07-2019 - |
Domanda
Ho ListBox WPF associato a ObservableCollection, quando la raccolta cambia, tutti gli elementi aggiornano la loro posizione.
La nuova posizione è memorizzata nella raccolta ma l'interfaccia utente non si aggiorna. Quindi ho aggiunto quanto segue:
void scenarioItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
ToolboxListItem.UpdatePositions();
lstScenario.ItemsSource = null;
lstScenario.ItemsSource = ToolboxListItem.ScenarioItems;
this.lstScenario.SelectedIndex = e.NewStartingIndex;
}
Impostando ItemsSource su null e quindi ricollegandolo, l'interfaccia utente viene aggiornata,
ma questa è probabilmente una codifica molto negativa: p
Suggerimenti?
Soluzione
Ho una Listbox associata a una proprietà dell'oggetto di tipo List<MyCustomType>()
e ho verificato che il seguente codice aggiorna la casella di riepilogo quando la Lista viene aggiornata.
void On_MyObjProperty_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
MyListBox.Items.Refresh();
}
Se i problemi persistono, scansiona la finestra di output VS IDE (Ctrl + W, O) e vedi se riesci a individuare eventuali errori di associazione segnalati.
Altri suggerimenti
WPF associando un elenco / raccolta di elementi a un ListBox, ma l'interfaccia utente non si aggiorna dopo l'aggiornamento degli elementi, Risolto .
Sono solo stupido. Mentre leggevo molto sull'uso di ObservableCollection<>
invece di List<>
, ho continuato a ignorare questo suggerimento e ho seguito altri suggerimenti, senza risultato. Sono tornato ai miei libri e riletto. È abbastanza ben spiegato che INotifyCollectionChange
è un must da usare perché ListBox
non fornisce l'interfaccia ObservableCollection
necessaria affinché RemoveRange()
aggiorni il suo display quando gli elementi cambiano nella raccolta.
Questo è il codice aggiornato:
private ObservableCollection<StringWrapper> m_AppLog;
ObservableCollection<StringWrapper> Log { get { return m_AppLog; } }
Abbastanza semplice e non richiede nient'altro (ad es. Refresh ()). Poiché ObservableCollection si occupa di attivare l'evento change, sono stato in grado di rimuovere la chiamata non necessaria:
// notify bound objects
OnPropertyChanged("Log");
<=> non supporta un aggiornamento di un thread che non lo ha creato. Poiché il mio elenco (un registro visivo per mostrare i recenti errori / messaggi informativi) può essere aggiornato da diversi thread, aggiungo per modificare il mio codice in questo modo per garantire che l'aggiornamento sia stato effettuato con il proprio dispatcher dell'elenco:
public void AddToLog(string message) {
if (Thread.CurrentThread != Dispatcher.Thread) {
// Need for invoke if called from a different thread
Dispatcher.Invoke(
DispatcherPriority.Normal, (ThreadStart)delegate() { AddToLog(message); });
}
else {
// add this line at the top of the log
m_AppLog.Insert(0, new StringWrapper(message));
// ...
Nota anche che <=> non supporta <=> contrariamente a <=>. Questo fa parte delle possibili regolazioni richieste quando si passa da Elenco a ObservableCollection.
Potrei avere un problema simile a quello che stai riscontrando, ma non sono sicuro.
Avevo un ObservableCollection<MyEntity>
e un ListBox
associati. Ma per qualche strano motivo il mio MyEntity
non è stato aggiornato quando ho cambiato le proprietà degli <=> oggetti nella lista.
Dopo aver cercato per un po 'ho trovato la pagina seguente e dovevo solo farti sapere:
http: / /www.wblum.org/listbind/net3/index.html
È un'ottima descrizione di cosa devi fare per ottenere un <=> da aggiornare quando l'elenco, o gli oggetti al suo interno, cambiano. Spero che tu possa trarne beneficio.
Ho avuto lo stesso problema ieri, ed è un pezzo di merda :) ... però non sto più impostando il mio su null. Nel mio scenario, lo sto impostando su MyList.ToArray () (dopo ogni volta che aggiungo all'elenco).
Ho visto più " oh, devi usare un ObservableList " < - schifo completo.
Ho visto più " oh, chiama 'Aggiorna' " < - schifo completo.
Per favore, perdona il mio turbamento, ma mi aspetto anche che funzioni :)
Questa è roba vecchia ma, usa un ObservableCollection. Se si desidera che l'interfaccia utente visualizzi gli aggiornamenti delle proprietà in Objects of the ObservableCollection, è necessario implementare INotifyPropertyChanged nella definizione di classe per quell'oggetto. Quindi aumentare l'evento di modifica della proprietà nel setter di ciascuna proprietà.
Public Class Session
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler _
Implements INotifyPropertyChanged.PropertyChanged
Private Sub NotifyPropertyChanged(ByVal info As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
End Sub
Private _name As String = "No name"
''' <summary>
''' Name of Session
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
NotifyPropertyChanged("Name")
End Set
End Property
Se hai un ObservableList di oggetti e stai modificando le proprietà all'interno di tali oggetti, la notifica non si applica poiché la raccolta non sta cambiando direttamente. Ho forzato la notifica dopo aver modificato le proprietà del mio oggetto utilizzando Insert () per aggiungere nuovamente l'oggetto modificato alla raccolta, quindi RemoveAt () per rimuovere la vecchia copia. Non è carino, ma funziona.
Per me, sembra più un bug in ListBox e ListView. Sono vincolante per un ObservableCollection, gli elementi nella raccolta implementano INotifyPropertyChanged. L'interfaccia utente non mostra elementi aggiunti quando premo dinamicamente il pulsante "aggiungi elemento", tuttavia ho un controllo contatore associato a MyCollection.Count. Questo controllo del contatore aumenta ogni volta che premo il pulsante "aggiungi elemento". Se ridimensiono la vista, la casella di riepilogo mostra tutti i miei elementi aggiunti. Pertanto, l'associazione ItemSource sul controllo ListBox è interrotta. Mi sono anche preoccupato di non creare un nuovo MyCollection in qualsiasi momento, il che avrebbe rotto l'associazione. Boo hoo.