如果我有以下布局:
public class A : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public B { get; set; }
}
public class B { public C { get; set; } }
public class C { public D { get; set; } }
public class D { public E { get; set; } }
//... add n classes
public class Z
{
public int Property
{
set
{
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Property"));
}
}
}
当A.B.C.D.E ... Z.Property发生变化时,我最简单的通知A的方式是什么?
当A内部的任何内容发生变化时,我希望它被标记为“脏”,这样我就可以告诉系统A需要保存。
答案 0 :(得分:1)
我最近正在研究这个完全相同的问题。我的方法是简单地让B,C,D等管理他们自己的Dirty状态,然后修改A的IsDirty
属性:
public bool IsDirty
{
get
{
return _isDirty || B.IsDirty || C.IsDirty /* etc */;
}
}
对我而言,这不仅简单,而且最有意义。如果的任何属性发生了变化, 就会变脏,而B,C,D等都是A的属性。
答案 1 :(得分:1)
我没有对它进行测试,但是应该对它进行测试。我不记得为什么,但我认为你无法处理PropertyChanged事件。您应该声明自己的委托(VoidHandler)。
public delegate void VoidHandler(object sender);
public class B // also C,D,E,...
{
// A.ItemChanged() will be wired to this SomethingChangedHandler.
// I heard you are saving. Exclude SomethingChangedHandler from save.
[field: NonSerialized]
public VoidHandler SomethingChangedHandler;
private c;
public C
{
set
{
// unwire handler from old instance of C
if(c != null)
c.SomethingChangedHandler -= ItemChanged;
// wire handler to new instance of C
value.SomethingChangedHandler += ItemChanged;
c = value;
// setting c is also change which require notification
ItemChanged(this);
}
get{}
}
// notify A about any change in B or in C
void ItemChanged(object sender)
{
if(SomethingChangedHandler != null)
SomethingChangedHandler(this);
}
}
答案 2 :(得分:1)
对于具有公共基类的业务线应用程序,我按照
执行此操作Implementing INotifyPropertyChanged - does a better way exist?
进行一些修改以检查“冒泡”属性。
基类
public bool HasAlteredState { get; protected set; }
public event PropertyChangedEventHandler PropertyChanged;
private void propertyObject_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
this.OnPropertyChanged(e.PropertyName);
}
protected virtual void RegisterSubPropertyForChangeTracking(INotifyPropertyChanged propertyObject)
{
propertyObject.PropertyChanged += new PropertyChangedEventHandler(propertyObject_PropertyChanged);
}
protected virtual void DeregisterSubPropertyForChangeTracking(INotifyPropertyChanged propertyObject)
{
propertyObject.PropertyChanged -= propertyObject_PropertyChanged;
}
protected virtual void OnPropertyChanged(string propertyName)
{
this.HasAlteredState = true;
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> selectorExpression)
{
if (selectorExpression == null)
throw new ArgumentNullException("selectorExpression");
MemberExpression body = selectorExpression.Body as MemberExpression;
if (body == null)
throw new ArgumentException("The body must be a member expression");
OnPropertyChanged(body.Member.Name);
}
protected bool SetField<T>(ref T field, T value, Expression<Func<T>> selectorExpression)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
if (field is INotifyPropertyChanged)
{
if (field != null) { this.DeregisterSubPropertyForChangeTracking((INotifyPropertyChanged)field); }
}
if (value is INotifyPropertyChanged)
{
if (value != null) { this.RegisterSubPropertyForChangeTracking((INotifyPropertyChanged)value); }
}
field = value;
OnPropertyChanged(selectorExpression);
return true;
}
子类
private IndividualName _name;
public IndividualName PersonName
{
get { return _name; }
set { SetField(ref _name, value, () => PersonName); }
}
<强>提供强>
<强>性能强>
此方法的性能受到影响......比使用字符串慢约20%。虽然指标和跟踪表明速度较慢但我实际上并没有说出差异,所以命中率值得重视:应用程序维护我参与开发的各种应用程序。
替代实施
为了获得更好的性能,您可以使用两种不同的SetField方法;第一个SetNotifyField将处理自己实现INotifyPropertyChanged(如上所述)的属性,第二个SetField将处理简单属性。即切出
if(field为INotifyPropertyChanged)...