MVVM 属性取决于对象图
我正在使用 WPF+MVVM
。
我有一个 VM
,其中包含 Customer
属性。 Customer
有一个 ObservableCollection
的 Orders
。每个Order
都有一个Items
的ObservableCollection
。每个Items
都有一个Price
。
现在,我的 VM
上有以下属性:
public double TotalPrice
{
return Customer.Orders.Sum(x => x.Items.Sum(y => y.Price));
}
问题是每当此对象图中的任何点发生更改时 - 应通知 UI TotalPrice
已更改- 但事实并非如此...
例如,如果客户
将从 A 更改为 B,或者添加订单,或者删除商品,或者更改商品价格等等。
有没有人对此有一个优雅的解决方案?
谢谢。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您是否支持 INotifyPropertyChanged / INotifyCollectionChanged 接口?您应该能够手动触发任何属性,例如在任何属性的 setter 中,您可以触发
OnPropertyChanged("TotalPrice")
,这样TotalPrice
的 UI 绑定也会更新。要处理依赖对象的更改,您可以提供事件或类似的内容,以便 ViewModel 能够订阅和处理底层对象更改,例如,您有一些服务正在从数据库重新加载订单,因此就像新的一样发生变化时,您也会更新 UI。在这种情况下,
OrdersService
应公开OrdersUpdated
事件,并且 ViewModel 可以订阅此事件并触发受影响属性的PropertyChanged
事件。让我们以某种情况为例,例如订单价格已更改。谁负责这个改变?这是由用户通过 UI 完成的吗?
Have you supported INotifyPropertyChanged / INotifyCollectionChanged interfaces in ViewModels? You should be able trigger any property manually, for instance in setter of any property you can trigger
OnPropertyChanged("TotalPrice")
so UI bindings forTotalPrice
would be updated as well.To handle dependent objects changes you can provide events or something like that so ViewModel would be able to subscribe and handle underlying object changes, for instance you have some service which is in chanrge of reloading of the Orders from a database, so as soo as new changes come you would update UI as well. In this case
OrdersService
should exposeevent OrdersUpdated
and ViewModel can subscribe for this event and in triggerPropertyChanged
events for affected properties.Let's consider some case as an example, for instance Order price has been changed. Who is in charge of this changes? Is this done via UI by an user?
你可以在这里找到我几天前写的一篇有趣的文章,内容完全正确。关于这个问题(及其解决方案......)
You can find here an interesting post written by me few days ago and it talks exactly about this problem (and its solution...)
您可以实现“累加器”属性,它将值的总和存储在对象集合中。监听这些值的变化并适当更新累加器。
(顺便说一句 - 我忘了提及,这实际上只适用于计算价值昂贵的情况。否则 Sll 的答案绝对是正确的选择。)
像这样的东西,省略了无聊的东西:
You might implement "accumulator" properties which store the sum of values in a collection of objects. Listen for changes to those values and update the accumulator appropriately.
(BTW - I forgot to mention that this one is really just for situations where the value is expensive to calculate. Otherwise Sll's answer is definitely the way to go.)
Something like this, with the boring stuff left out:
我认为我最新的 WPF 尝试 MadProps 可以很好地处理这种情况。看一下这个主从场景示例。只要存在从正在编辑的 Item 到 VM 的路径(例如,
VM.TheCustomer.SelectedOrder.SelectedItem
或简单的VM.SelectedItem
),PropChanged 事件就会传播到虚拟机,您可以编写:关于添加和删除项目或订单,我只需在
ICommand
代码中添加显式更新,例如VM.UpdateTotalPrice();
。管理 ObservableCollections 及其中的项目的订阅和取消订阅可能很棘手。I think my latest WPF endeavor MadProps handles this scenario pretty well. Take a look at this example master-detail scenario. As long as there a path from the Item being edited to the VM (for example,
VM.TheCustomer.SelectedOrder.SelectedItem
or simplyVM.SelectedItem
), the PropChanged event will propogate up to the VM and you can write:Regarding adding and removing Items or Orders, I would just put an explicit update in the
ICommand
code, something likeVM.UpdateTotalPrice();
. Managing subscriptions and unsubscriptions to ObservableCollections and the items in them can be tricky.