您好,我有 3 个关于 MVVM 模型的问题。
- 难道没有办法绕过这种多余的
PropertyChanged("PropName");
- 将 POCO 对象包装到 WPF
INotifyPropertyChanged, IDataErrorInfo
的最佳方法是什么 - 我应该如何与ViewModel内部的(WPfWrapers - POCO)进行交互 - 通过强制转换或属性...
谢谢。
3个答案:
您可以在 .NET 社区中找到引发 PropertyChanged 事件的替代方法,而无需将"PropName"作为字符串参数传递。但是,它们都有其他缺点(例如性能)。
最好的方法是直接在模型中实现 INotifyPropertyChanged 和 IDataErrorInfo。这并不总是可能的。如果您需要包装模型类,那么您可以查看 DataModel 概念。
我不确定我是否正确理解了最后一个问题,但这里有一个答案。视图模型或数据模型应直接与模型交互。但是这些类不应以直接方式与视图交互。在此类场景中使用接口(例如 IView)。
可在此处找到详细信息:WPF 应用程序框架 (WAF)
-
是的,您可以使用 Lamdba 表达式执行此操作。但这会花费一些处理器时间(进行一些快速测量:这种方法比使用字符串常量慢约 200 倍。在频繁访问的 POCO 上使用表达式时,请记住这一点):
private string ExtractPropertyName<T>( Expression<Func<T>> propertyExpresssion ) { if ( propertyExpresssion == null ) { throw new ArgumentNullException( "propertyExpresssion" ); } var memberExpression = propertyExpresssion.Body as MemberExpression; if ( memberExpression == null ) { throw new ArgumentException( "The expression is not a member access expression.", "propertyExpresssion" ); } var property = memberExpression.Member as PropertyInfo; if ( property == null ) { throw new ArgumentException( "The member access expression does not access a property.", "propertyExpresssion" ); } if ( !property.DeclaringType.IsAssignableFrom( this.GetType( ) ) ) { throw new ArgumentException( "The referenced property belongs to a different type.", "propertyExpresssion" ); } var getMethod = property.GetGetMethod( true ); if ( getMethod == null ) { // this shouldn't happen - the expression would reject the property before reaching this far throw new ArgumentException( "The referenced property does not have a get method.", "propertyExpresssion" ); } if ( getMethod.IsStatic ) { throw new ArgumentException( "The referenced property is a static property.", "propertyExpresssion" ); } return memberExpression.Member.Name; } private string myProperty; public string MyProperty { get { return myProperty; } set { myProperty = value; this.RaisePropertyChanged( ( ) => MyProperty ); } } protected void RaisePropertyChanged<T>( Expression<Func<T>> propertyExpression ) { var propertyName = ExtractPropertyName( propertyExpression ); this.RaisePropertyChanged( propertyName ); }
-
我认为您不必包装它们(除了创建相应的视图模型)。POCO 用作模型,接口由视图模型实现。
- 当您不包装 POCO 时,此问题已过时。
关于你的第一个问题:看看这篇文章
并进行谷歌搜索
有很多方法(和讨论)
我的2美分:
第一其次
还可以选择在视图模型中使用依赖项属性。很多人似乎不喜欢这样做,因为他们是 wpf 的一部分并且具有线程相关性(您只能从创建该特定对象的线程调用依赖项属性方法)
我个人从未发现这是一个问题,因为您的视图既依赖于 wpf 又具有线程亲和性,因此即使使用了 INotifyPropertyChanged,您仍然必须从正确的线程触发 PropertyChanged 事件。
依赖项属性具有内置的通知支持,并且不需要 wpf 执行任何反射,因此它们对于数据绑定速度更快(但设置/获取速度较慢,尽管时间尺度较小)
你的场景可能与我的不同,但我认为这是值得关注的:)
可以使用名为"CallerMemberName"的 .NET 4.5 新功能来避免对属性名称进行硬编码。