主从视图中聚合详细信息值
我在一些自定义实体中有主从关系。假设我有以下结构:
class Master : INotifyPropertyChanged
{
public int Id { get; set; } // + property changed implementation
public string Name { get; set; } // + property changed implementation
public ObservableCollection<Detail> Details { get; }
}
class Detail : INotifyPropertyChanged
{
public int Id { get; private set; }
public string Description { get; set; }
public double Value { get; set; } // + property changed implementation
}
我的目标是拥有一个 ListView,使用 GridView,显示 Master 对象的列表。当我选择特定的 Master 时,我将有一个单独的 ListView 来显示详细信息,以便进行编辑。基本上,这是一个相当标准的主从视图。
但是,我还希望 Master 的 GridView 显示该 master 的所有 Detail 元素的总和,即: Details.Select(d => d.Value).Sum();
这是使用自定义 IValueConverter 相当容易显示。我可以将详细信息集合直接转换为双显示总和,并通过 IValueConverter 将 TextBlock 的文本绑定到详细信息 OneWay。这将起作用,并在我打开窗口时显示正确的值。
但是,如果我更改详细信息成员之一,这将不会更新(即使详细信息实现了 INotifyPropertyChanged),因为集合本身仍然相同(ObservableCollection 引用没有更改)。
我希望在主列表中有一个聚合值,显示详细列表中的总和(或平均值/计数/等),并在用户更改详细信息属性时保持最新状态。我该如何实施呢?
编辑:
理想情况下,我更希望有一种方法可以完成此任务,而不涉及直接更改 Master 类。有问题的应用程序正在使用 MVVM 模式,我真的不想为了实现特定的视图而更改我的模型类。有没有办法在不将自定义逻辑引入模型的情况下做到这一点?
I have a master-detail relationship in some custom entities. Say I have the following structure:
class Master : INotifyPropertyChanged
{
public int Id { get; set; } // + property changed implementation
public string Name { get; set; } // + property changed implementation
public ObservableCollection<Detail> Details { get; }
}
class Detail : INotifyPropertyChanged
{
public int Id { get; private set; }
public string Description { get; set; }
public double Value { get; set; } // + property changed implementation
}
My goal is to have a ListView, using a GridView, showing a list of Master objects. When I select a specific Master, I'll have a separate ListView for the details, allowing editing. Basically, a fairly standard Master-Detail view.
However, I also want the GridView for the Master to show the Sum of all of that master's Detail elements, ie: Details.Select(d => d.Value).Sum();
This is fairly easy to display using a custom IValueConverter. I can convert from the details collection directly to a double displaying sum, and bind a TextBlock's Text to the Details OneWay, via the IValueConverter. This will work, and show the correct values when I open the window.
However, if I change one of the detail members, this will not update (even though detail implements INotifyPropertyChanged), since the collection itself is still the same (the ObservableCollection reference hasn't changed).
I want to have an aggregated value in a master list, showing the sum (or average/count/etc) within the detail list, and have this stay up to date when the user changes properties in details. How can I go about implementing this?
Edit:
Ideally, I would prefer if there is a means of accomplishing this that doesn't involve changing the Master class directly. The application in question is using the MVVM pattern, and I'd really prefer to not change my Model classes in order to implement a specific View. Is there a way to do this without introducing custom logic into the model?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我正在考虑 UI 的可能性,您可以在其中显式绑定并通过命令执行绑定/更新...但似乎最简单的方法是扩展 ObservableCollection 以添加/删除每个详细信息的侦听器实例作为其添加/删除,然后在其中任何一个发生更改时触发 CollectionChanged 。称之为 DeeplyObservableCollection。
最坏的情况是,如果您无法正确重写所需的所有方法,则必须将 ObservableCollection 包装为另一种类型...
I was considering possibilities with the UI where you'd make the binding explicit and perform binding/updates from a command... but it seems that the easiest way to do it would be to extend the ObservableCollection to add/remove listeners to each Detail instance as its added/removed, then just fire CollectionChanged when any of them change. Call it DeeplyObservableCollection<T>.
Worst case you'd have to wrap an ObservableCollection in another type if you can't properly override all the methods you need...