Bind to total of an items field in an ObservableCollection and update when values change

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



Bind to total of an items field in an ObservableCollection and update when values change



I have an ObservableCollection that populates a datagrid in WPF. I need to bind to the total of the "Hours" column, and have that total update when a value in the "Hours" column is changed. I can achieve this by listening to the "LostFocus" event and running a function, but would like to try my hand at binding.



The issue I am running into, is the NotifyPropertyChanged event will not fire when an items property in the collection is changed.



The sortie class NotifyPropertyChanged will fire, but the collection doesn't interpret that as its own property changing. How can I listen to the sortie PropertyChanged from the collection in the missions class?



My Models


public class Mission : INotifyPropertyChanged

private ObservableCollection<Sortie> sorties;
public ObservableCollection<Sortie> Sorties

get return this.sorties;
set


if (this.sorties != value)

this.sorties = value;
this.NotifyPropertyChanged("Sorties");



public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)

if (this.PropertyChanged != null)

this.PropertyChanged(this, new PropertyChangedEventArgs(propName));




public class Sortie : INotifyPropertyChanged

private double hours;
public double Hours

get return this.hours;
set

if (this.hours != value)

this.hours = value;
this.NotifyPropertyChanged("Hours");



public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)

if (this.PropertyChanged != null)

this.PropertyChanged(this, new PropertyChangedEventArgs(propName));





I didn't bother posting my XAML or View Model, as I am confident I can solve the issue once I learn how to trigger a PropertyChanged event for the collection and I wanted to spare you having to read through massive amounts of code. If you believe it is needed however, let me know.





Multidupe. OC doesn't listen to INPC of its children. You have to manage this.
– Will
Aug 31 '16 at 19:56




2 Answers
2



Write a readonly property in the parent viewmodel that calculates the value.


public double SortieHours => Sorties.Sum(x => x.Hours);



Parent viewmodel handles PropertyChanged on each item in Sorties, and CollectionChanged on Sorties. In CollectionChanged on Sorties, you have to add/remove PropertyChanged handlers from Sortie instances as they're added and removed. When you get a new Sorties collection (you might want to make that setter private for this reason), you need to toss out all the old handlers and add new ones.


PropertyChanged


Sorties


CollectionChanged


Sorties


CollectionChanged


Sorties


PropertyChanged


Sortie


Sorties



Now, whenever a Sortie is added or removed, or its Hours changes, or somebody hands you a new Sorties collection, raise PropertyChanged:


Sortie


Hours


Sorties


PropertyChanged


OnPropertyChanged(nameof(SortieHours));



And bind that property to whatever you like in the XAML.



This looks horrible (because it is), but what else are you going to do?



A lot of people would advise you to give Sortie an HoursChanged event. PropertyChanged is annoying for this type of case because it can get raised for multiple different properties and you have to check which one. And it's a magic string thing.


Sortie


HoursChanged


PropertyChanged



Above is C#6. For C#5,


public double SortieHours get return Sorties.Sum(x => x.Hours);

OnPropertyChanged("SortieHours");





Ugh....so ugly, but can't deny that it works. Thank you.
– Tronald
Aug 31 '16 at 20:05





not sure why this is considered ugly, seems rational to me. +1
– NappingRabbit
Aug 27 at 11:38





@NappingRabbit It’s ugly because there are so many events and handlers involved in keeping a single value up to date. It’s rational, certainly: It’s your only option, and it works. But it’s not pretty.
– Ed Plunkett
Aug 27 at 11:54



I found this link to be a big help. It creates a base class for ObservableCollections to "AutoMagicly" add the PropertyChanged events of the collection items to the CollectionChanged event.






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard