33

我有绑定到 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

建议?

4

8 回答 8

77

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

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

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

于 2008-10-31T12:15:24.623 回答
11

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

我只是愚蠢。虽然我已经阅读了很多关于 usingObservableCollection<>而不是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 时可能需要进行的调整的一部分。

于 2009-12-05T10:33:47.477 回答
6

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

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

搜索了一段时间后,我找到了以下页面,我只需要让您知道:

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

它很好地描述了ListBox当列表或其中的对象发生更改时您必须做什么才能更新。希望您能从中受益。

于 2010-11-09T21:55:01.127 回答
4

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

我见过多个“哦,你需要使用 ObservableList”<-- 完全是废话。

我见过多个“哦,叫‘刷新’”<——完全是废话。

请原谅我的不安,但我也希望这能奏效:)

于 2008-10-31T10:32:35.287 回答
4

我知道它已经有点老了,但今天我遇到了同样的问题。我更新了 ObservableCollection 中对象的属性,但视图没有更新,但后来我发现了这篇很棒的文章。

I think it's a very clean solution to manually trigger the update of an ObservableCollection:

CollectionViewSource.GetDefaultView(this.myObservableCollection).Refresh();
于 2019-11-26T02:34:45.173 回答
2

这是旧东西,但是使用 ObservableCollection。如果您希望 UI 看到 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
于 2010-04-13T15:14:48.960 回答
0

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

于 2009-04-26T02:12:45.843 回答
0

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

于 2014-10-10T16:05:49.410 回答