wpf 提高属性的更好方法改变了 MVVMLight

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43485381/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 14:03:55  来源:igfitidea点击:

Better way to raise property changed MVVMLight

c#wpfmvvm

提问by Adam

Created a project using MVVM Light. It is common for the ViewModels to have a lot of properties that look like this

使用 MVVM Light 创建了一个项目。ViewModel 有很多类似这样的属性是很常见的

class TestModel
{
    public string DisplayValue { get; set; }
}

class TestViewModel : ViewModelBase
{
    public string DisplayValue
    {
         private TestModel model = new TestModel();

         get
         {
              return model.DisplayValue;
         }
         set
         {
              if (model.DisplayValue != value)
              {
                   model.DisplayValue = value;
                   RaisePropertyChanged();
              }
         }
    }
}

Sometimes the property is not in the model and is backed by a local private field instead. This approach works fine, but there is a ton of boilerplate code. How can the code duplication be reduced?

有时该属性不在模型中,而是由本地私有字段支持。这种方法工作正常,但有大量的样板代码。如何减少代码重复?

Are there any better solutions than the one I proposed or is there something built into MVVM Light that I missed?

有没有比我提出的更好的解决方案,或者我错过了 MVVM Light 内置的一些东西?

回答by dotNET

My version of the boilerplate MVVM Light property looks like this:

我的样板 MVVM Light 属性版本如下所示:

private string _Prop = "";

public string Prop
{
  get { return _Prop; }
  set { Set(ref _Prop, value); }
}

which is pretty much the thinnest one can get, made possible through the use of Setfunction provided by the underlying ObservableObjectclass (you could use ViewModelBasetoo).

这几乎是最薄的一个,通过使用Set底层ObservableObject类提供的函数(你也可以使用ViewModelBase)来实现。

Edit

编辑

In C# 7 and above you could squeeze it even further:

在 C# 7 及更高版本中,您可以进一步压缩它:

private int p = 0;
public int P
{
  get => p;
  set => Set(ref p, value);
}

回答by Adam

In my application the model is a pure data store and is used primarily for reading and writing to a SQL Server. The model contains the backing fields for all the properties in the ViewModel that get saved to the server. So it makes sense to only have fields in the model and only access them through the ViewModel

在我的应用程序中,模型是一个纯数据存储,主要用于读取和写入 SQL Server。该模型包含保存到服务器的 ViewModel 中所有属性的支持字段。所以模型中只有字段并且只能通过 ViewModel 访问它们是有意义的

class TestModel
{
    public string displayValue;
    public override bool Equals(object obj)
    {
        if (obj.GetType() != typeof(TestModel))
                return false;

        var testObj = obj as TestModel;
        return testObj?.GetHashCode() == testValue?.GetHashCode();
    }

    public override int GetHashCode()
    {
        return displayValue.GetHashCode();
    }
}

GetHashCode will be the only thing that needs to get updated when additional fields are added to the class. Since it is a field it is possible to pass it by reference to a common function and use it in all of the properties.

GetHashCode 将是在类中添加其他字段时唯一需要更新的内容。由于它是一个字段,因此可以通过引用通用函数来传递它并在所有属性中使用它。

class TestViewModel:ViewModelBase
{
    private TestModel model = new TestModel();
    public string DisplayValue
    {
        get { return model.displayValue; }
        set { SetIfChanged(ref model.displayValue, value, RunCalculations); }
    }


    public bool SetIfChanged<T>(ref T field, T value, Action MoreWork, [CallerMemberName] string propertyName = null)
    {
        if (!Equals(field, value))
        {
            field = value;
            MoreWork.Invoke();
            RaisePropertyChanged(propertyName);
            return true;
        }

        return false;
    }

    private void RunCalculations()
    {
       // Do some work before RaisePropertyChanged()
    }
}

This accepts all types, override EqualTo as required for equality to work properly. It can also run additional calculations as required.

这接受所有类型,根据需要覆盖 EqualTo 才能正常工作。它还可以根据需要运行额外的计算。

It would be nice if this could be removed from the ViewModel like the MVVM Light Set method, but I haven't been able to figure that out.

如果可以像 MVVM Light Set 方法那样从 ViewModel 中删除它,那就太好了,但我一直无法弄清楚。

回答by A. S. Mahadik

MVVM light provide set methods as below example you directly used it.

MVVM 灯提供设置方法,如下例您直接使用它。

class TestViewModel : ViewModelBase
{
   private TestModel model = new TestModel();

   public string DisplayValue
  {
     get{return model.DisplayValue;}
     set{ Set(()=>DisplayValue, ref model.DisplayValue, value); }
  }   
}