我在一些自定义实体中有一个主 - 细节关系。说我有以下结构:
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
}
我的目标是使用GridView创建一个ListView,显示一个Master对象列表。当我选择一个特定的Master时,我会有一个单独的ListView来获取详细信息,允许编辑。基本上,一个相当标准的Master-Detail视图。
但是,我还希望Master的GridView能够显示所有Master的Detail元素的总和,即:Details.Select(d => d.Value).Sum();
使用自定义IValueConverter显示相当容易。我可以将详细信息集合直接转换为双显示总和,并通过IValueConverter将TextBlock的Text绑定到Details OneWay。这将起作用,并在我打开窗口时显示正确的值。
但是,如果我更改其中一个详细信息成员,则不会更新(即使detail实现了INotifyPropertyChanged),因为集合本身仍然相同(ObservableCollection引用未更改)。
我希望在主列表中有一个聚合值,显示详细信息列表中的总和(或平均值/计数/等),并在用户更改详细信息属性时保持最新状态。我该如何实施呢?
编辑:
理想情况下,我更愿意,如果有一种方法可以实现这一点,而不涉及直接更改Master类。有问题的应用程序正在使用MVVM模式,我真的更愿意不更改我的Model类以实现特定的View。有没有办法在不将自定义逻辑引入模型的情况下做到这一点?
答案 0 :(得分:3)
我正在考虑使用UI的可能性,你可以在其中显式绑定并从命令执行绑定/更新......但似乎最简单的方法是扩展ObservableCollection以添加/删除侦听器将每个Detail实例添加/删除后,只需在其中任何一个更改时触发CollectionChanged。称之为 DeeplyObservableCollection&lt; T&gt;。
class Master : INotifyPropertyChanged
{
public int Id { get; set; } // + property changed implementation
public string Name { get; set; } // + property changed implementation
public double Sum {get {return Details.Sum(x=>x.Value);}}
public DeeplyObservableCollection<Detail> Details { get; }
// hooked up in the constructor
void OnDOCChanged(object sender, CollectionChangedEventArgs e)
{ OnPropertyChanged("Sum"); }
}
最糟糕的情况是,如果无法正确覆盖所需的所有方法,则必须将ObservableCollection包装在另一种类型中...