Eine bessere Möglichkeit, Daten zu zwingen, die von WPF ListBox aktualisiert werden?


Answers

WPF bindet eine Liste / Auflistung von Elementen an eine ListBox, aber die Benutzeroberfläche wird nach Aktualisieren der Elemente nicht aktualisiert, Gelöst .

Ich bin nur dumm. Während ich viel über die Verwendung von ObservableCollection<> statt von List<> gelesen habe, ignorierte ich diesen Vorschlag weiter und folgte anderen Vorschlägen, ohne Erfolg. Kehre zu meinen Büchern zurück und lese nach. Es ist ziemlich gut erklärt, dass ObservableCollection<> ein Muss ist, weil List<> nicht die INotifyCollectionChange Schnittstelle bereitstellt, die für die ListBox benötigt ListBox , um ihre Anzeige zu aktualisieren, wenn sich die Elemente in der Auflistung ändern.

Das ist der aktualisierte Code:

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

Ziemlich einfach und benötigt 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 / Infomeldungen) aus verschiedenen Threads aktualisiert werden kann, füge ich meinen Code auf diese Weise hinzu, um sicherzustellen, dass das Update mit dem eigenen Dispatcher der Liste 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 erforderlich sind, wenn von List zu ObservableCollection gewechselt wird.

Question

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

Die neue Position wird in der Sammlung gespeichert, die Benutzeroberfläche wird jedoch 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 schlechtes programmieren: p

Vorschläge?




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

Ich habe mehrere "Oh, Sie müssen eine ObservableList verwenden" <- komplette Mist zu sehen.

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

Bitte verzeihen Sie meine Verwirrung, aber ich würde auch erwarten, dass dies funktioniert :)




Wenn Sie über eine ObservableList von Objekten verfügen und die Eigenschaften innerhalb dieser Objekte ändern, gilt die Benachrichtigung nicht, da die Auflistung nicht direkt geändert wird. Ich habe die Benachrichtigung erzwungen, nachdem ich meine Objekteigenschaften geändert habe, indem ich Insert () verwendet habe, um mein geändertes Objekt der Sammlung hinzuzufügen, und dann RemoveAt (), um die alte Kopie zu entfernen. Es ist nicht schön, aber es funktioniert.