2009-10-14 4 views
2

У меня есть отношения между деталями и деталями в некоторых пользовательских объектах. Скажем, у меня есть следующая структура:Совокупные значения деталей в режиме 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 
} 

Моя цель есть ListView, с помощью GridView, отображающий список магистерских объектов. Когда я выберу конкретный Мастер, у меня будет отдельный ListView для деталей, позволяющий редактировать. В принципе, довольно стандартный вид Master-Detail.

Однако, я также хочу GridView для Учителя, чтобы показать сумму всех элементов Detail этого хозяина, а именно: Details.Select(d => d.Value).Sum();

Это довольно легко отобразить с помощью пользовательского IValueConverter. Я могу конвертировать из коллекции деталей непосредственно в двойную отображаемую сумму и привязать текст TextBlock к деталям OneWay через IValueConverter. Это будет работать и покажет правильные значения при открытии окна.

Однако, если я изменяю один из деталей детали, это не будет обновляться (даже если деталь реализует INotifyPropertyChanged), так как сама коллекция по-прежнему одна и та же (ссылка ObservableCollection не изменилась).

Я хочу иметь агрегированное значение в главном списке, отображающее сумму (или среднее значение/счет/и т. Д.) В списке подробностей и сохраняя ее, когда пользователь изменяет свойства в деталях. Как я могу это реализовать?


Edit:

В идеале, я бы предпочел, если есть средство достижения этого, что не предполагает изменения класса Master непосредственно. В рассматриваемом приложении используется шаблон MVVM, и я бы предпочел не менять классы модели, чтобы реализовать определенный вид. Есть ли способ сделать это без введения пользовательской логики в модель?

ответ

3

Я рассматривал возможности с пользовательским интерфейсом, где вы делаете привязку явным и выполняете привязку/обновления из команды ... но кажется, что самый простой способ сделать это - расширить ObservableCollection для добавления/удаления слушателей каждого экземпляра Detail, поскольку он добавлен/удален, а затем просто запускает CollectionChanged при изменении любого из них. Назовите это 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"); } 
} 

В худшем случае вам придется обернуть ObservableCollection в другой тип, если вы не можете должным образом переопределить все методы, необходимые ...

+1

+1, так как это работает. Я подумал об этом, но мне бы очень хотелось сделать это, не меняя мастер-класс в идеальном мире. Реализация этого означает изменение модели, чтобы позволить View работать, что мне просто не нравится ... –

+0

Ну, не совсем ... Это не сильно отличается от написания ObservableCollection в первую очередь. – Will

+0

За исключением того, что теперь у моей сущности есть свойство «Сумма», это чисто проблема с представлением и не связанная с сущностью ... –