Is there a way to raise some OnPropertyChanged event for a computed property that uses the "child" property in the collection?

Is there a way to raise some OnPropertyChanged event for a computed property that uses the "child" property in the collection?

A small example:

I have a simple WPF application with a DataGrid showing client properties. I am using Entity Framework 5, the CodeFirst approach, so I wrote my classes manually using my own implementation of INotifyPropertyChanged.

 public partial class Customer : INotifyPropertyChanged { private string _firstName; public virtual string FirstName { get { return _firstName; } set { _firstName = value; OnPropertyChanged("FirstName"); OnPropertyChanged("FullName"); } } private string _lastName; public virtual string LastName { get { return _lastName; } set { _lastName = value; OnPropertyChanged("LastName"); OnPropertyChanged("FullName"); } } public virtual ICollection<Car> Cars { get; set; } public virtual ICollection<Invoice> Invoices { get; set; } ... } 

Now in the same class I created 3 calculated properties:

  public string FullName { get { return (FirstName + " " + LastName).Trim(); } } public int TotalCars { get { return Cars.Count(); } } public int TotalOpenInvoices { get { if (Invoices != null) return (from i in Invoices where i.PayedInFull == false select i).Count(); else return 0; } } 

FullName automatically updated in the DataGrid because I call OnPropertyChanged("FullName");

I found an implementation example of INotifyCollectionChanged, which I can probably use to automatically update TotalCars when something is added or removed from ICollection: http://www.dotnetfunda.com/articles/article886-change-notification-for-objects-and -collections.aspx

But what is the best approach to running OnPropertyChange("TotalOpenInvoices") when the ( PayedInFull ) property changes inside Invoices ( Invoices )?

Doing something like OnPropertyChanged("Customer.TotalOpenInvoices"); Invoice class doesn't seem like a trick ... :)

+4
source share
2 answers

Do you have control over what is included in your collections? If you do this, you can create the Parent property in the Invoice object, and when it is added to the collection, set the parent for your Client. Then, when PaidInFull is installed, run Customer.OnPropertyChanged ("TotalOpenInvoices") or call the method on the Customer object to recalculate your invoices.

Performing parent-child relationships in C # and .Net

+3
source

This assumes that the invoice and the client implement IPropertyChanged. Just change your collection to ObservableCollection and view the CollectionChanged property.

When adding new invoices, attach an event handler to the PropertyChanged event of this invoice. When an item is removed from the collection, delete this event handler.

Then just call the NotifyPropertyChanged function in the TotalOpenInvoices property.

For example (not fully tested, but should be close):

Invoice

 public class Invoice : INotifyPropertyChanged { private bool payedInFull = false; public bool PayedInFull { get { return payedInFull; } set { payedInFull = value; NotifyPropertyChanged("PayedInFull"); } } #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } #endregion } 

Customer

 public class Customer : INotifyPropertyChanged { public Customer() { this.Invoices.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Invoices_CollectionChanged); } ObservableCollection<Invoice> Invoices { get; set; } public int TotalOpenInvoices { get { if (Invoices != null) return (from i in Invoices where i.PayedInFull == false select i).Count(); else return 0; } } void Invoices_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { foreach (Invoice invoice in e.NewItems) { invoice.PropertyChanged += new PropertyChangedEventHandler(invoice_PropertyChanged); NotifyPropertyChanged("TotalOpenInvoices"); } foreach (Invoice invoice in e.OldItems) { invoice.PropertyChanged -= new PropertyChangedEventHandler(invoice_PropertyChanged); NotifyPropertyChanged("TotalOpenInvoices"); } } void invoice_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "PayedInFull") NotifyPropertyChanged("TotalOpenInvoices"); } #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } #endregion } 

Please note that each class can be assigned to one class that implements INotifyPropertyChanged, for example, the ViewModelBase class, but this is not necessary for this example.

+1
source

Source: https://habr.com/ru/post/1444437/


All Articles