我有一个使用INotifyPropertyChanged来发送属性更新的WPF应用程序。我喜欢它的是它让你能够在不调用所有setter代码的情况下发出属性更改的信号。当你有两个相互更新的链接字段,或者你有代码在每个setter上保存更改并且你不想多次触发保存时,这对于用户实际上是一次更改是很方便的。
然而,这种方法的明显缺点是,属性名称中的错误或者您发送通知的视图模型会使您陷入困境并且只显示和运行时。
我查看了依赖项属性,但无法找到任何可以让您进行“软更新”的内容:让UI知道该属性已更改但是避免调用在UI导致更改时通常会运行的所有代码viewmodel。
我是否有某种方法可以获得允许软更新的属性系统并在编译时捕获通知问题?
答案 0 :(得分:3)
如果基础问题是属性名称中的错误,则存在编译时解决方案,例如将“属性名称”参数设置为表达式树而不是字符串。
http://michaelsync.net/2009/04/09/silverlightwpf-implementing-propertychanged-with-expression-tree
Caliburn.Micro库在其PropertyChangedBase类中也包含此方法。
答案 1 :(得分:3)
我喜欢Foson针对属性名称进行“早期绑定”的解决方案,并且无需保留属性名称的字符串副本。这是我个人使用的实现的核心:
public virtual string GetName<T>(Expression<Func<T>> expression)
{
return GetMemberName(expression);
}
/// <summary>Abstraction for actually finding the name of the target of the expression</summary>
private static string GetMemberName<T>(Expression<Func<T>> expression)
{
if (expression != null)
{
var myMemberExpression = expression.Body as MemberExpression;
if (myMemberExpression != null && myMemberExpression.Member != null)
{
return myMemberExpression.Member.Name;
}
}
return string.Empty;
}
此代码驻留在一个名为NameResolver的类中,我的ViewModelBase类将其包装
NotifyChange(Expression<Func<T>> expression)
然后客户端代码类似于:
private int _myBindable;
public int MyBindable { get { return _myBindable; } set { _myBindable = value; NotifyChange(() => MyBindable); }
关于将GUI通知与更新底层内容分离的概念,当代码中发生的任何触发UI更新的事件发生时,您可以调用除属性setter之外的NotifyChange()方法。因此,GUI设置你的属性,这会触发一些逻辑,但你不会在那里提出更改通知 - 你从任何地方提出它,具体来说,你想通知UI有关某事。