您好,我有 3 个关于 MVVM 模型的问题。
- 有没有办法绕过那个多余的
PropertyChanged("PropName");
- 将 POCO 对象包装到 WPF 的最佳方法是什么
INotifyPropertyChanged, IDataErrorInfo
- 我应该如何在 ViewModel 中与(WPfWrapers - POCO)交互 - 通过强制转换或属性......
谢谢。
您好,我有 3 个关于 MVVM 模型的问题。
PropertyChanged("PropName");
INotifyPropertyChanged, IDataErrorInfo
谢谢。
这里有3个答案:
您可以在.NET 社区中找到在不将“PropName”作为字符串参数传递的情况下引发 PropertyChanged 事件的替代方法。但是,它们都有其他缺点(例如性能)。
最好的方法是直接在 Model 中实现 INotifyPropertyChanged 和 IDataErrorInfo。这并不总是可能的。如果你需要包装你的模型类,那么你可以看看DataModel概念。
我不确定我是否理解最后一个问题,但这里有一个答案。ViewModel 或 DataModel 应该直接与 Model 交互。但是这些类不应该直接与视图交互。在这种情况下使用接口(例如 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 用作模型,接口由视图模型实现。
还可以选择在视图模型中使用依赖属性。很多人似乎不喜欢这样做,因为它们是 wpf 的一部分并且具有线程亲和力(您只能从创建该特定对象的线程调用依赖属性方法
我个人从未发现这是一个问题,因为您的视图既依赖于 wpf 又具有线程关联性,因此即使使用了 INotifyPropertyChanged,您仍然必须从正确的线程触发 PropertyChanged 事件。
Dependecy 属性内置了通知支持,并且不需要 wpf 进行任何反射,因此它们用于数据绑定更快(但设置/获取速度较慢,尽管时间范围很小)
您的情况可能与我的情况不同,但我认为它看起来很有趣:)
您可以使用名为“CallerMemberName”的 .NET 4.5 新功能来避免对属性名称进行硬编码。