wake-up-neo.net

Eine bessere Möglichkeit, datengebundene WPF-ListBox zu aktualisieren?

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

Die neue Position wird in der Sammlung gespeichert, aber die Benutzeroberfläche wird nicht aktualisiert.

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

Durch Setzen der ItemsSource auf null und anschließendes erneutes Binden wird die Benutzeroberfläche aktualisiert.

aber das ist wahrscheinlich sehr schlecht codierung: p

Vorschläge?

29
TimothyP

Ich habe eine Listbox, die an eine Objekteigenschaft des Typs List<MyCustomType>() gebunden ist, und ich habe überprüft, dass der folgende Code die Listbox aktualisiert, wenn die Liste aktualisiert wird.

void On_MyObjProperty_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
   MyListBox.Items.Refresh();
}

Wenn Sie immer noch Probleme haben, scannen Sie das VS IDE - Ausgabefenster (Strg + W, O), und prüfen Sie, ob Sie die festgestellten Bindungsfehler feststellen können.

74
Gishu

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 weiter und folgte anderen Vorschlägen ohne Erfolg. Kehrte zu meinen Büchern zurück und las sie erneut. Es ist ziemlich gut erklärt, dass ObservableCollection<> ein Muss ist, da List<> nicht die INotifyCollectionChange-Schnittstelle zur Verfügung stellt, die die ListBox benötigt, um ihre Anzeige zu aktualisieren, wenn sich die Elemente in der Sammlung ändern.

Dies ist der aktualisierte Code:

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

Ziemlich einfach und erfordert nichts anderes (z. B. Refresh ()). Da ObservableCollection sich selbst um das Auslösen des Änderungsereignisses kümmert, konnte ich den unnötigen Aufruf entfernen:

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

ObservableCollection unterstützt kein Update durch einen Thread, der es nicht erstellt hat. Da meine Liste (ein visuelles Protokoll zur Anzeige der letzten Fehler/Infomeldungen) von verschiedenen Threads aus aktualisiert werden kann, muss ich meinen Code auf diese Weise anpassen, 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<>RemoveRange() nicht unterstützt. Dies ist Teil der möglichen Einstellungen, die erforderlich sind, wenn von List zu ObservableCollection gewechselt wird.

9
rolling

Ich habe vielleicht ein ähnliches Problem wie Sie, aber ich bin mir nicht sicher.

Ich hatte einen ObservableCollection<MyEntity> und eine ListBox daran gebunden. Aber aus irgendeinem seltsamen Grund wurde meine ListBox nicht aktualisiert, als ich die Eigenschaften der MyEntity-Objekte in der Liste änderte.

Nachdem ich eine Weile gesucht hatte, fand ich die folgende Seite und musste Sie nur wissen lassen:

http://www.wblum.org/listbind/net3/index.html

Es ist eine sehr gute Beschreibung dessen, was Sie tun müssen, um eine ListBox zu aktualisieren, wenn sich die Liste oder die darin enthaltenen Objekte ändern. Ich hoffe, Sie werden davon profitieren.

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

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

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

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

4
Timothy Khouri

Dies ist altes Zeug, aber verwenden Sie eine ObservableCollection. Wenn Sie möchten, dass die Benutzeroberfläche Aktualisierungen für Eigenschaften in den Objekten der ObservableCollection anzeigt, müssen Sie INotifyPropertyChanged in der Klassendefinition für dieses Objekt implementieren. Erhöhen Sie dann das Eigenschaftsänderungsereignis im Setter jeder Eigenschaft.

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
2
KP.

Für mich sieht es eher nach einem Fehler in ListBox und ListView aus. Ich bin an eine ObservableCollection gebunden, die Elemente in der Auflistung implementieren INotifyPropertyChanged. Die Benutzeroberfläche zeigt keine hinzugefügten Elemente an, wenn ich dynamisch auf die Schaltfläche "Element hinzufügen" drücke. Allerdings habe ich ein Zählersteuerelement, das an MyCollection.Count gebunden ist. Diese Zählersteuerung erhöht sich jedes Mal, wenn ich auf die Schaltfläche "Artikel hinzufügen" drücke. Wenn ich die Ansicht verkleinere, werden im Listenfeld alle meine hinzugefügten Elemente angezeigt. Daher ist die ItemSource-Bindung für das ListBox-Steuerelement beschädigt. Ich habe auch darauf geachtet, zu keinem Zeitpunkt eine neue MyCollection zu erstellen, die die Bindung bricht. Boo-Hoo.

0
flobadob

Wenn Sie über eine ObservableList mit Objekten verfügen und Sie Eigenschaften in diesen Objekten ändern, wird die Benachrichtigung nicht angewendet, da die Auflistung nicht direkt geändert wird. Ich habe eine Benachrichtigung erzwungen, nachdem ich meine Objekteigenschaften geändert hatte, indem Sie mit Insert () mein geändertes Objekt erneut zur Auflistung hinzufügen und dann RemoveAt () zum Entfernen der alten Kopie. Es ist nicht hübsch, aber es funktioniert.

0
Peter