在“主 - 详细信息”视图中聚合详细信息值

时间:2009-10-14 19:14:19

标签: c# wpf mvvm master-detail

我在一些自定义实体中有一个主 - 细节关系。说我有以下结构:

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。有没有办法在不将自定义逻辑引入模型的情况下做到这一点?

1 个答案:

答案 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包装在另一种类型中...