强制数据绑定WPF ListBox更新的更好方法是什么?

时间:2008-10-31 10:16:53

标签: wpf data-binding listbox observablecollection

我有一个绑定到ObservableCollection的WPF ListBox, 当集合发生变化时,所有项目都会更新其位置。

新位置存储在集合中,但UI不会更新。 所以我添加了以下内容:

    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然后再次绑定它,UI将被更新,

但这可能是非常糟糕的编码:p

建议?

8 个答案:

答案 0 :(得分:74)

我有一个Listbox绑定到类型为List<MyCustomType>()的对象属性,并且我验证了以下代码在更新List时更新了列表框。

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

如果您仍然遇到问题,请扫描VS IDE输出窗口(Ctrl + W,O),看看是否可以发现报告的任何绑定错误。

答案 1 :(得分:10)

WPF将列表/项目集合绑定到ListBox,但更新项目后UI未刷新,已解决

我只是愚蠢。虽然我已经阅读了很多关于使用ObservableCollection<>而不是List<>的内容,但我只是继续忽略这一建议并继续遵循其他建议,但无济于事。回到我的书并重读。很好地解释了ObservableCollection<>是必须使用的,因为当List<>项目中的项目发生更改时,INotifyCollectionChange不提供ListBox更新其显示所需的private ObservableCollection<StringWrapper> m_AppLog; ObservableCollection<StringWrapper> Log { get { return m_AppLog; } } 界面

这是更新的代码:

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

非常简单,不需要任何其他内容(例如Refresh())。因为ObservableCollection负责触发change事件,所以我能够删除不必要的调用:

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<>与{{1}}相反。这是从List切换到ObservableCollection时所需的可能调整的一部分。

答案 2 :(得分:6)

我可能遇到类似的问题,但我不确定。

我绑定了ObservableCollection<MyEntity>ListBox。但是对于某些奇怪的原因,当我更改列表中ListBox个对象的属性时,我的MyEntity没有被更新。

搜索了一段时间后,我找到了以下页面,我只是想让你知道:

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

这是一个非常好的描述,当列表或其中的对象发生更改时,您需要做什么才能更新ListBox。希望你能从中受益。

答案 3 :(得分:4)

昨天我遇到了同样的问题,这是一个完整的废话:) ...我不会再将我的设置为null了。在我的场景中,我将其设置为MyList.ToArray()(每次添加到列表后)。

我见过多个“哦,你需要使用一个ObservableList”&lt; - 完全废话。

我见过多次“哦,打电话'刷新'”&lt; - 完全废话。

请原谅我的沮丧,但我也希望这可行:)

答案 4 :(得分:2)

这是旧的东西但是,使用ObservableCollection。如果您希望UI在ObservableCollection的Objects中查看属性的更新,则需要在该对象的类defenition中实现INotifyPropertyChanged。然后在每个属性的setter中引发属性更改事件。

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

答案 5 :(得分:0)

如果您有Observable对象列表,并且您正在更改这些对象内的属性,则通知不会应用,因为集合不会直接更改。通过使用Insert()将我更改的对象重新添加到集合中,然后使用RemoveAt()删除旧副本,我在更改对象属性后强制通知。它不漂亮,但它有效。

答案 6 :(得分:0)

对我而言,它看起来更像是ListBox和ListView中的错误。我绑定了一个ObservableCollection,集合中的项目实现了INotifyPropertyChanged。当我动态按下我的“添加项目”时,用户界面不显示添加的项目。但是我有一个绑定到MyCollection.Count的计数器控件。每次按下我的“添加项目”时,此计数器控件都会递增。按钮。如果我调整视图大小,列表框会显示我添加的所有项目。因此,ListBox控件上的ItemSource绑定被破坏。我也注意不要在任何时候创建一个新的MyCollection,这会破坏绑定。 Boo hoo。

答案 7 :(得分:0)

我知道它已经有些老了,但是今天我遇到了同样的问题。我更新了ObservableCollection内部的对象的属性,并且视图未更新,但是随后发现了this很棒的文章。

我认为手动触发ObservableCollection的更新是一种非常干净的解决方案:

CollectionViewSource.GetDefaultView(this.myObservableCollection).Refresh();