2008-10-31 3 views
29

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

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

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 к нулю, а затем снова его связывания, пользовательский интерфейс обновляется,

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

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

+0

Не могли бы вы дать более подробную информацию о том, что вы подразумеваете под «когда коллекция меняется, все элементы обновляют свою позицию», так что я могу быть уверен, что правильно отвечаю на ваш вопрос? – Donnelle

ответ

72

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

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

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

+0

Это, кажется, решает проблему, поэтому я переведу вопрос об ошибке в другой пост. Спасибо! – TimothyP

+0

Спасибо, Гишу! –

+0

Прошло уже два года с тех пор, как кто-то прокомментировал это ... Большое спасибо! –

4

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

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

Я видел несколько «о, звоните« Обновить »« < - полный дерьмо.

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

+0

Поверьте мне, я могу понять ваше расстройство, поэтому никакого преступления не было. Я попытался использовать GetBindingExpression, но это retuls в null: p – TimothyP

+0

мое «GetBindingExpression» не возвращает null ... но даже если я назову «UpdateTarget», он ничего не делает :(... только в этом случае ... он отлично работает для всего остального. –

0

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

9

WPF привязывает список/набор элементов к ListBox, но UI не обновляется после обновленных элементов, Решено.

Я просто глуп. Хотя я много читал об использовании 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.

+0

Я тоже сделал эту ошибку, и мне потребовалось очень много времени, прежде чем я нашел решение. +1. – JSideris

2

Это старый материал, но используйте 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

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

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

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

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

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

+0

это очень здорово, спасибо большое! Особенно интересно, что вам просто нужно реализовать INotifyPropertyChanged для класса, содержащегося в «ListBox». –

+1

Этот домен продается. –

0

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

+0

Lolz, в моей ситуации проблема заключалась в том, что кто-то действительно реализовал класс ObservableCollection! Итак, моя коллекция на самом деле не выполняла INotifyCollectionChanged, хотя она называлась ObservableCollection. Jeez. Как только я удалил оскорбительное пространство имен и использовал System.Collections.ObjectModel, все было в порядке. DOH! – flobadob

Смежные вопросы