Eine bessere Möglichkeit zum Erzwingen von Daten gebunden WPF ListBox zu aktualisieren?



Answers

WPF bindet eine Liste / Sammlung von Elementen an eine ListBox, aber die Benutzeroberfläche wird nicht aktualisiert, nachdem Elemente aktualisiert wurden, Gelöst .

Ich bin nur dumm. Während ich viel über die Verwendung von ObservableCollection<> anstelle von List<> gelesen hatte, ignorierte ich diesen Vorschlag einfach und ging anderen Vorschlägen nach, ohne Erfolg. Kehre zu meinen Büchern zurück und lese sie noch einmal. Es ist ziemlich gut erklärt, dass ObservableCollection<> ein Muss ist, da List<> die INotifyCollectionChange Schnittstelle nicht zur Verfügung INotifyCollectionChange , die für die ListBox , um ihre Anzeige zu aktualisieren, wenn sich die Elemente in der Auflistung ändern.

Dies ist der aktualisierte Code:

private ObservableCollection<StringWrapper> m_AppLog;
ObservableCollection<StringWrapper> Log { get { return m_AppLog; } }

Ziemlich einfach und erfordert nichts anderes (zB Refresh ()). Da ObservableCollection selbst dafür sorgt, dass das Änderungsereignis ausgelöst wird, konnte ich den unnötigen Aufruf entfernen:

// notify bound objects
OnPropertyChanged("Log");

ObservableCollection unterstützt keine Aktualisierung durch einen Thread, der sie nicht erstellt hat. Da meine Liste (ein visuelles Protokoll zum Anzeigen der letzten Fehler / Info-Nachrichten) von verschiedenen Threads aktualisiert werden kann, füge ich hinzu, um meinen Code auf diese Weise anzupassen, um sicherzustellen, dass das Update mit dem listeneigenen Dispatcher durchgeführt wurde:

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));
        // ...

Beachten Sie auch, dass ObservableCollection<> im Gegensatz zu List<> nicht RemoveRange() unterstützt. Dies ist Teil der möglichen Anpassungen, die beim Wechsel von List zu ObservableCollection erforderlich sind.

Question

Ich habe WPF ListBox, die an eine ObservableCollection gebunden ist. Wenn sich die Sammlung ändert, aktualisieren alle Elemente ihre Position.

Die neue Position wird in der Sammlung gespeichert, aber die Benutzeroberfläche wird nicht aktualisiert. Also habe ich folgendes hinzugefügt:

    void scenarioItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        ToolboxListItem.UpdatePositions();
        lstScenario.ItemsSource = null;
        lstScenario.ItemsSource = ToolboxListItem.ScenarioItems;
        this.lstScenario.SelectedIndex = e.NewStartingIndex;
    }

Wenn Sie die ItemsSource auf null setzen und dann erneut binden, wird die Benutzeroberfläche aktualisiert.

aber das ist wahrscheinlich sehr schlecht codieren: p

Vorschläge?




Wenn Sie über eine ObservableList für Objekte verfügen und die Eigenschaften in diesen Objekten ändern, gilt die Benachrichtigung nicht, da sich die Auflistung nicht direkt ändert. Ich erzwinge die Benachrichtigung, nachdem ich meine Objekteigenschaften geändert habe, indem ich mit Insert () mein geändertes Objekt wieder in die Sammlung eingefügt habe, und dann RemoveAt (), um die alte Kopie zu entfernen. Es ist nicht schön, aber es funktioniert.




Ich hatte gestern das selbe Problem und es ist ein kompletter Mist :) Ich setze meinen nicht mehr auf null. In meinem Szenario setze ich es auf MyList.ToArray () (nach jedem Hinzufügen zu der Liste).

Ich habe mehrere gesehen "Oh, Sie müssen eine ObservableList verwenden" <- kompletter Mist.

Ich habe mehrere gesehen "oh, rufen Sie Refresh '" <- Komplette Mist.

Bitte vergib mir meine Verstimmung, aber ich würde auch erwarten, dass das funktioniert :)




Links