有没有办法为计算属性触发某种OnPropertyChanged
事件,该计算属性在集合中使用“子实体”的属性?
一个小例子:
我有一个简单的WPF应用程序,其中DataGrid显示了Customer属性。 我正在使用Entity Framework 5,CodeFirst方法,因此我使用自己的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; }
...
}
现在在同一个类中我创建了3个计算属性:
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
会在DataGrid中自动更新,因为我正在调用OnPropertyChanged("FullName");
我找到了一个INotifyCollectionChanged实现的示例,我可以使用它来在ICollection中添加或删除某些内容时自动更新TotalCars
:
http://www.dotnetfunda.com/articles/article886-change-notification-for-objects-and-collections.aspx
但是当ICollection(OnPropertyChange("TotalOpenInvoices")
)中的属性(PayedInFull
)发生变化时触发Invoices
的最佳方法是什么?
在Invoice类中执行类似OnPropertyChanged("Customer.TotalOpenInvoices");
的操作似乎没有办法......:)
答案 0 :(得分:3)
您是否可以控制收藏品内容?如果这样做,您可以在Invoice对象上创建Parent属性,并在将其添加到集合中时,将父级设置为Customer。然后,当PaidInFull设置好后,运行Customer.OnPropertyChanged(“TotalOpenInvoices”)或调用Customer对象上的方法重新计算发票。
答案 1 :(得分:1)
这假设Invoice和Customer都实现了IPropertyChanged。只需将您的集合更改为ObservableCollection,并观察CollectionChanged属性。
添加新发票时,将事件处理程序连接到该发票的PropertyChanged事件。从集合中删除项目时,请删除该事件处理程序。
然后,只需在TotalOpenInvoices属性上调用NotifyPropertyChanged函数。
例如(未完全测试,但应该关闭):
<强>发票强>
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
}
<强>客户强>
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
}
请注意,每个类都可以抽象为实现INotifyPropertyChanged的单个类,例如ViewModelBase类,但这个示例不一定是必需的。