MVVM模型应该是什么样的?

MVVM模型应该是什么样的?,mvvm,model,poco,inotifypropertychanged,idataerrorinfo,Mvvm,Model,Poco,Inotifypropertychanged,Idataerrorinfo,你好,我有3个关于MVVM模型的问题 有没有办法绕过冗余的PropertyChanged(“PropName”) 将POCO对象包装到WPFINotifyPropertyChanged,IDataErrorInfo 我应该如何与(WPfWrapers-POCO)内部ViewModel交互-通过强制转换或属性 谢谢 是的,您可以使用Lamdba表达式来实现这一点。但这将花费一些处理器时间(进行了一些快速测量:这种方法比使用字符串常量慢大约200倍。在频繁访问的POCO上使用表达式时请记住这一点):

你好,我有3个关于MVVM模型的问题

  • 有没有办法绕过冗余的
    PropertyChanged(“PropName”)
  • 将POCO对象包装到WPF
    INotifyPropertyChanged,IDataErrorInfo
  • 我应该如何与(WPfWrapers-POCO)内部ViewModel交互-通过强制转换或属性
  • 谢谢

  • 是的,您可以使用Lamdba表达式来实现这一点。但这将花费一些处理器时间(进行了一些快速测量:这种方法比使用字符串常量慢大约200倍。在频繁访问的POCO上使用表达式时请记住这一点):

    私有字符串ExtractPropertyName(表达式PropertyExpression)
    {
    if(PropertyExpression==null)
    {
    抛出新ArgumentNullException(“PropertyExpression”);
    }
    var memberExpression=propertyExpression.Body作为memberExpression;
    if(memberExpression==null)
    {
    抛出新ArgumentException(“表达式不是成员访问表达式。”,“PropertyExpression”);
    }
    var property=memberExpression.Member作为PropertyInfo;
    if(属性==null)
    {
    抛出新ArgumentException(“成员访问表达式不访问属性。”,“PropertyExpression”);
    }
    如果(!property.DeclaringType.IsAssignableFrom(this.GetType()))
    {
    抛出新ArgumentException(“引用的属性属于其他类型。”,“PropertyExpression”);
    }
    var getMethod=property.getMethod(true);
    if(getMethod==null)
    {
    //这不应该发生-表达式将在达到此程度之前拒绝该属性
    抛出新ArgumentException(“引用的属性没有get方法。”,“PropertyExpression”);
    }
    if(getMethod.IsStatic)
    {
    抛出新ArgumentException(“引用的属性是静态属性。”,“PropertyExpression”);
    }
    返回memberExpression.Member.Name;
    }
    私有财产;
    公共字符串MyProperty
    {
    得到
    {
    归还我的财产;
    }
    设置
    {
    myProperty=值;
    this.raiseProperty已更改(()=>MyProperty);
    }
    }
    受保护的void RaisePropertyChanged(表达式属性Expression)
    {
    var propertyName=ExtractPropertyName(propertyExpression);
    this.RaisePropertyChanged(propertyName);
    }
    
  • 我认为您不必包装它们(除了创建一个共同响应的视图模型)。POCO用作模型,接口由viewmodel实现

  • 如果不包装POCO,则此问题已过时
  • 关于你的第一个问题: 有一个

    有很多方法(和讨论)

    我的2美分:

    以下是三个答案:

  • 您可以找到引发PropertyChanged事件的替代方法,而无需将“PropName”作为字符串参数传递到中。但是,它们都有其他缺点(例如性能)

  • 最好的方法是直接在模型中实现INotifyPropertyChanged和IDataErrorInfo。这并不总是可能的。如果您需要包装您的模型类,那么您可以看看这个概念

  • 我不确定我是否理解了最后一个问题,但这里有一个答案。ViewModel或DataModel应该直接与模型交互。但是这些类不应该直接与视图交互。在此类场景中使用接口(如IView)


  • 更多信息可在此处找到:

    还可以选择在viewmodel中使用依赖项属性。很多人似乎不喜欢这样做,因为他们是wpf的一部分,并且具有线程关联性(您只能从创建特定对象的线程调用dependency属性方法)

    我个人从未发现这是一个问题,因为您的视图既依赖于wpf,又具有线程关联性,因此即使使用了INotifyPropertyChanged,您仍然必须从正确的线程触发PropertyChanged事件

    Dependecy属性具有内置的通知支持,不需要wpf进行任何反射,因此数据绑定速度更快(但设置/获取速度较慢,尽管时间尺度较小)


    您的场景可能与我的场景有所不同,但我认为值得一看:)

    您可以使用.NET 4.5名为“CallerMemberName”的新功能来避免对属性名称进行硬编码。

    如果POCO将实现它们,它们将依赖于WPF。INotifyPropertyChanged与WPF无关。此外,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 );
    }