Подтвердить что ты не робот

Лучший способ заставить данные, связанные с WPF ListBox, обновить?

У меня есть WPF ListBox, связанный с ObservableCollection, когда коллекция меняется, все элементы обновляют свою позицию.

Новая позиция сохраняется в коллекции, но пользовательский интерфейс не обновляется. Поэтому я добавил следующее:

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

Установив источник ItemsSource равным null, а затем снова привязывая его, пользовательский интерфейс обновляется,

но это, вероятно, очень плохое кодирование: p

Предложения?

4b9b3361

Ответ 1

У меня есть список, привязанный к объекту, имеющему тип List<MyCustomType>(), и я проверил, что следующий код обновляет список при обновлении списка.

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

Если вы все еще сталкиваетесь с проблемами, отсканируйте окно вывода VS IDE (Ctrl + W, O) и посмотрите, можете ли вы сообщить о любых сообщенных ошибках.

Ответ 2

WPF привязывает список/коллекцию элементов к ListBox, но пользовательский интерфейс не обновляется после обновления элементов, Решено.

Я просто глуп. Хотя я много читал об использовании ObservableCollection<> вместо List<>, я просто продолжал игнорировать это предложение и пошел дальше других предложений, но безрезультатно. Вернулся к моим книгам и перечитал. Достаточно хорошо объяснить, что ObservableCollection<> необходимо использовать, потому что List<> не предоставляет интерфейс INotifyCollectionChange, необходимый для ListBox, чтобы обновлять его отображение, когда элементы меняются в коллекции.

Это обновленный код:

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

Довольно просто и не требует ничего другого (например, Refresh()). Поскольку ObservableCollection заботится о запуске события изменения, я смог удалить ненужный вызов:

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

ObservableCollection не поддерживает обновление потоком, который его не создал. Поскольку мой список (визуальный журнал для отображения последних сообщений об ошибках/информации) может быть обновлен из разных потоков, я добавляю, чтобы настроить мой код таким образом, чтобы убедиться, что обновление было выполнено с помощью собственного диспетчера:

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

Также обратите внимание, что ObservableCollection<> не поддерживает RemoveRange() вопреки List<>. Это часть возможных настроек, необходимых при переключении с List на ObservableCollection.

Ответ 3

У меня может быть аналогичная проблема с тем, что у вас есть, но я не уверен.

Я привязал к нему ObservableCollection<MyEntity> и a ListBox. Но по какой-то странной причине мой ListBox не обновлялся, когда я изменил свойства объектов MyEntity в списке.

После поиска какое-то время я нашел следующую страницу, и я просто должен был сообщить вам:

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

Это очень хорошее описание того, что вам нужно сделать, чтобы обновить ListBox при изменении списка или объектов внутри него. Надеясь, вы выиграете от этого.

Ответ 4

У меня была такая же проблема вчера, и это полный кусок дерьма:)... Я больше не устанавливаю свой номер в null. В моем сценарии я устанавливаю его в MyList.ToArray() (после каждого добавления в список).

Я видел несколько "о, вам нужно использовать ObservableList" < - полное дерьмо.

Я видел несколько "о, звоню" Обновить "и" полное дерьмо ".

Пожалуйста, простите мою расстроенность, но я также ожидал, что это сработает:)

Ответ 5

Это старый материал, но используйте ObservableCollection. ЕСЛИ вы хотите, чтобы пользовательский интерфейс видел обновления свойств в объектах ObservableCollection, вам необходимо реализовать INotifyPropertyChanged в классе для этого объекта. Затем поднимите событие измененного свойства в установщике каждого свойства.

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

Ответ 6

Если у вас есть ObservableList объектов и вы изменяете свойства внутри этих объектов, уведомление не применяется, поскольку коллекция не изменяется напрямую. Я меняю уведомление после изменения свойств объекта, используя Insert(), чтобы повторно добавить мой измененный объект в коллекцию, а затем RemoveAt(), чтобы удалить старую копию. Это не очень, но это работает.

Ответ 7

Для меня это больше похоже на ошибку в ListBox и ListView. Я привязываюсь к ObservableCollection, элементы в реализации коллекции INotifyPropertyChanged. Пользовательский интерфейс не показывает никаких добавленных элементов, когда я динамически нажимаю кнопку "добавить элемент", однако у меня есть счетчик, связанный с MyCollection.Count. Это управление счетчиком увеличивается каждый раз, когда я нажимаю кнопку "добавить элемент". Если я изменил размер представления, в списке появится все мои добавленные элементы. Таким образом, привязка ItemSource в элементе управления ListBox нарушена. Я также позаботился о том, чтобы не создавать новый MyCollection в любой момент, который нарушил бы привязку. Boo hoo.