[英]How to implement INotifyPropertyChanged for aggregate properties
Say I have a collection of order line objects...假设我有一组订单行对象...
public class OrderLine {
public decimal Qty { get; set; }
public decimal Cost { get; set; }
public decimal CostExt {
get {
return Qty * Cost;
}
}
}
I can implement INotifyPropertyChanged
in Qty
and Cost
when those values are modified, and my view will be notified of the update.当这些值被修改时,我可以在
Qty
和Cost
实现INotifyPropertyChanged
,并且我的视图将收到更新通知。 However, CostExt
is an aggregate value, it relies on both Qty
and Cost
, meaning that I am forced to invoke PropertyChanged
on it as well, in each property that it relates to!然而,
CostExt
是一个聚合值,它依赖于Qty
和Cost
,这意味着我也被迫在它相关的每个属性中调用PropertyChanged
! In a large view-model with potentially hundreds of properties and various aggregates sprinkled throughout, this would become a nightmare to maintain.在一个可能有数百个属性和各种聚合体的大型视图模型中,这将成为维护的噩梦。 Is there a way to coerce the view to re-examine the aggregate without any undue suffering?
有没有办法强迫见地重新审视总体而没有任何过度的痛苦?
Edit : OK, just to be clear, the design pattern I'm looking for will allow me to simply tell the aggregate( CostExt
, in this case) what properties it should consider integral to its binding.编辑:好的,只是要清楚,我正在寻找的设计模式将允许我简单地告诉聚合(在本例中为
CostExt
)它应该考虑哪些属性是其绑定的组成部分。 Qty
, Cost
, and any other property involved should need to know nothing about the fact that they are being read from by the aggregate. Qty
、 Cost
和任何其他涉及的属性应该不需要知道它们正在被聚合读取的事实。 The end result will be a much cleaner view-model without the need to rewrite existing properties because a new aggregate requires them.最终结果将是一个更清晰的视图模型,而无需重写现有属性,因为新的聚合需要它们。 Simple, eh?
很简单吧?
Very simple, Raise ProperttyChanged
event on CostExt
when ever other dependent properties are changed.非常简单,当其他相关属性发生更改时,在
CostExt
上CostExt
ProperttyChanged
事件。
public decimal Qty
{
get { return _qty; }
set
{
_qty = value;
OnPropertyChanged("Qty");
OnPropertyChanged("CostExt");
}
}
Your (complete)implementation should be like您的(完整)实现应该是这样的
public class OrderLine : INotifyPropertyChanged
{
private decimal _qty;
private decimal _cost;
public decimal Qty
{
get { return _qty; }
set
{
_qty = value;
OnPropertyChanged("Qty");
OnPropertyChanged("CostExt");
}
}
public decimal Cost
{
get { return _cost; }
set
{
_cost = value;
OnPropertyChanged("Cost");
OnPropertyChanged("CostExt");
}
}
public decimal CostExt
{
get
{
return Qty * Cost;
}
}
#region Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
If you don't want to manually implement INotifyPropertyChanged, use Fody PropertyChanged .如果您不想手动实现 INotifyPropertyChanged,请使用Fody PropertyChanged 。
Your code:您的代码:
[ImplementPropertyChanged]
public class Person
{
public string GivenNames { get; set; }
public string FamilyName { get; set; }
public string FullName
{
get
{
return string.Format("{0} {1}", GivenNames, FamilyName);
}
}
}
When compiled:编译时:
public class Person : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
string givenNames;
public string GivenNames
{
get { return givenNames; }
set
{
if (value != givenNames)
{
givenNames = value;
OnPropertyChanged("GivenNames");
OnPropertyChanged("FullName");
}
}
}
string familyName;
public string FamilyName
{
get { return familyName; }
set
{
if (value != familyName)
{
familyName = value;
OnPropertyChanged("FamilyName");
OnPropertyChanged("FullName");
}
}
}
public string FullName
{
get
{
return string.Format("{0} {1}", GivenNames, FamilyName);
}
}
public virtual void OnPropertyChanged(string propertyName)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Notice that properties that depends on other properties will get picked up.请注意,依赖于其他属性的属性将被选取。
How about something like this:这样的事情怎么样:
public class OrderLine : INotifyPropertyChanged {
decimal qty;
decimal cost;
public decimal Qty {
get { return qty; }
set { SetNotify(ref qty, value, "Qty", "CostExt"); }
}
public decimal Cost {
get { return cost; }
set { SetNotify(ref cost, value, "Cost", "CostExt"); }
}
public decimal CostExt {
get {
return Qty * Cost;
}
}
protected void SetNotify<T>(ref T property, T value, params string[] notificationProperties) {
var method = PropertyChanged;
if (method != null) {
foreach (var p in notificationProperties) {
method(this, new PropertyChangedEventArgs(p));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.