WPF:如何创建可绑定的集合

时间:2012-08-23 11:52:58

标签: wpf

我的应用程序有一个后台线程,它以键/值对的形式定期从外部源检索数据。我希望将这些数据暴露给绑定,可能是通过将它们存储在某种静态(?)模型中,因为整个应用程序中的大量视图都需要这些数据。这些密钥可能有数百个,并且每个客户可能有所不同,因此我不能简单地创建一个带有每个值的属性的INotifyPropertyChanged模型。

应用程序在任何时候都可以看到多个视图,并且每个视图都有许多控件(通常是文本框),我想将它们绑定到上面集合中的各个项目。更新集合中的值时,绑定到该项目的任何控件都应更改以反映新值。我假设ObservableCollection在这里不合适,因为对单个项目的更改将导致所有控件更新,无论它们绑定到哪个项目?

为了进一步增加混合的复杂性,一些值(数字)将需要格式化以便显示,例如小数位数,或添加后缀,如“伏特”。格式化规则是用户定义的,因此我无法将它们硬编码到(例如)XAML绑定的StringFormat表达式中。理想情况下,我应该能够访问原始值(例如用于计算)和格式化版本(用于显示目的)。我确信使用一些聪明的WPF功能必须能够实现后者!

如果我能解决这些要求,我将不胜感激。

编辑:值得一提的是,我之前尝试将模型作为某种集合来实现。问题是它最初不会填充所有值,而这些只会在一段时间后添加。当他们最终被添加时,绑定控件不会更新 - 可能是因为它最初无法绑定到缺失值。

3 个答案:

答案 0 :(得分:1)

我会采用不同的方法,即Event Aggregation的变体。我将有一个管理整个集合的类(可能是像franssu建议的单例类),但不是直接绑定到该类中的集合,而是创建更具体的单个视图的较小模型。

当您的主模型收到一个新项目时,它会发布一个事件,由较小的模型使用,该模型可以检查新项目并确定是否应该将该项目添加到其内部集合(个别视图中的项目)必然)。如果它不“属于”他们的观点,他们可以简单地忽略该事件。

您可以使用类似的事件发布来更新项目等,但如果您绑定到实际项目,则可能不需要。

答案 1 :(得分:1)

只需实现INotifyCollectionChanged接口和INotifyPropertyChanged,就会得到像ObservableCollection这样的集合。

但是,如果您从Collection中选择一个Item(例如ObservableCollection)并且您更改了该项,则其他控件将不会更新。因此,如果您的集合中有一个Person类,并且您更改了一个人的名称,则其他控件将无法获取该人员的新名称。

在Person对象中,你仍然需要实现INotifyPropertyChanged接口,并在你的名字改变时引发事件。

所以我想告诉你的是:一个带有接口INotifyCollectionChanged的集合只会告诉绑定的控件:有一个新的Item,删除了一个项目或者一个项目索引已经改变但是如果项目本身的变化。

所以你需要一个提供上述点的Collection和一个集合所包含的Item,如果它的属性发生变化,它会引发事件。

答案 2 :(得分:0)

ObservableCollection在这里很完美。您应该会发现绑定到ItemsControl的标准ObservableCollection只会更新已更改项目的控件,而不会更新集合中的每个项目。

这就是ObservableCollection存在的原因 - 它引发的事件专门识别已更改的项目,以便UI可以合理地处理它们。

我已经在一个小型WPF应用程序本地测试了它,它工作正常。值得注意的是,虚拟化项目面板在滚动时可能会破坏这种行为......

编辑:重新阅读您的问题,您实际上说“当集合中的值更新时...”如果您的集合包含类的实例,并且您更新了类的属性,那么甚至不需要ObservableCollection来实现这一点 - 您只需要该类来实现INotifyPropertyChanged