开发者

Aggregate detail values in Master-Detail view

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 imple开发者_如何学运维menting 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?


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>.

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"); }
}

Worst case you'd have to wrap an ObservableCollection in another type if you can't properly override all the methods you need...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜