如何编写MVVM属性?

时间:2012-07-17 12:33:53

标签: c# .net mvvm

使用MVVM,我总是会看到这两种属性的方法:

    private int myProperty;
    public int MyProperty
    {
        get { return myProperty; }
        set
        {
            myProperty = value;
            NotifyPropertyChanged("MyProperty");
        }
    }

    private int myProperty;
    public int MyProperty
    {
        get { return myProperty; }
        set
        {
            myProperty = value;
            NotifyPropertyChanged(m => m.MyProperty);
        }
    }

第一个使用硬编码字符串NotifyPropertyChanged,第二个使用lambda表达式NotifyPropertyChanged。我不想创建一个辩论,询问什么是更好的解决方案,但我想了解这两个解决方案之间的差异是什么。使用其中一个的后果是什么?

如果我错了,请纠正我,但lambda表达式解决方案应该使用更多内存,并且应该比硬编码字符串慢,因为基类的NotifyPropertyChanged方法使用委托和反射。但硬编码的字符串解决方案可能会创建愚蠢的错误,因为它是一个字符串,没有什么可以告诉我我正确写了它。

3 个答案:

答案 0 :(得分:3)

第二个表达式会在属性名称更改时生成编译器错误,或者会自动更改(通过VS或ReSharper中的重命名支持)。

基本上,您获得了对属性名称的编译器支持。提供给通知的错误名称意味着数据绑定会中断。使用字符串名称,这种破坏将是沉默的。

在一个小的用户界面中,我认为选择是无关紧要的,但是在一个包含大量UI层的大型应用程序中,从长远来看,对bug的额外支持可以自行解决。

性能不会有问题更慢,不要忘记,绑定是反射驱动的。一如既往,表现是相对的。硬编码版本在技术上会更快,因为它不需要反映元数据中的属性名称。多快了,我不确定。

答案 1 :(得分:1)

不是为每个属性重复NotifyPropertyChanged的代码,而是觉得下面的代码更清晰

在ViewModel Base中创建一个Set方法

protected bool Set<T>(Expression<Func<T>> selectorExpression, ref T field, T value)
{
    if (EqualityComparer<T>.Default.Equals(field, value))
       return false;
    field = value;
    RaisePropertyChanged(selectorExpression);
    return true;
}

并将其用作

string title;
public string Title
{
   get { return title; }
   set { Set(() => Title, ref title, value); }
}

答案 2 :(得分:0)

我在实现INotifyPropertyChanged的基类中使用以下方法,它非常简单方便:

public void NotifyPropertyChanged()
    {
        StackTrace stackTrace = new StackTrace();

        MethodBase method = stackTrace.GetFrame(1).GetMethod();

        if (!(method.Name.StartsWith("get_") || method.Name.StartsWith("set_")))
        {
            throw new InvalidOperationException("The NotifyPropertyChanged() method can only be used from inside a property");
        }

        string propertyName = method.Name.Substring(4);

        RaisePropertyChanged(propertyName);
    }