2017-04-19 67 views
3

使用MVVM Light創建項目。這是常見的的ViewModels有很多看起來像這樣更好的方法來提高屬性更改MVVMLight

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(); 
       } 
     } 
    } 
} 

性能有時屬性不是在模型中,由本地私人領域的支持來代替。這種方法工作正常,但有大量的樣板代碼。代碼重複如何減少?

有沒有比我提出的解決方案更好的解決方案,還是MVVM Light中內置的東西,我錯過了?

回答

6

我的樣板MVVM光屬性的版本是這樣的:

private string _Prop = ""; 

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

這是相當多最薄的一款可以得到,通過使用Set功能由底層ObservableObject類提供成爲可能(你也可以使用ViewModelBase)。

+0

你可以省略'nameof(Prop)',其中一個重載使用CallerMemberName,所以'set {ref _Prop,value); }'給出相同的結果 – Adam

+0

做Set(ref _Prop,value);包括if(_Prop!= value)? – gts13

+0

@ gts13:我認爲它確實如此。 – dotNET

0

在我的應用程序中,該模型是一個純數據存儲區,主要用於讀取和寫入SQL Server。該模型包含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將需要額外時字段添加到類以獲取更新的唯一的東西。因爲它是一個字段,所以可以通過引用一個通用函數來傳遞它,並在所有屬性中使用它。

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() 
    } 
} 

此接受所有類型,覆蓋EqualTo按要求平等才能正常工作。它也可以根據需要運行額外的計算。

這將是很好,如果這可以從ViewModel中移除像MVVM Light Set方法,但我一直無法弄清楚。

+0

@MickyD更新使其工作。 – Adam

+0

燦爛。謝謝你,先生。爲你的+1餅乾:) – MickyD

+1

如果你有'空'字段,我會推薦'object.Equals(field,value)'。同樣在我的項目中,我有類似的東西,但它在提升屬性發生變化之前執行了'Action'(這可能會非常有用),並且該函數返回一個布爾值,指示該值是否實際發生了更改,因此我可以通過簡單的方式觸發其他代碼'if'語句。 – grek40

0

MVVM提供的設置方法如下面的例子直接使用它。

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

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

有什麼辦法可以傳入一個函數,只有當屬性改變纔會執行? – Adam

+0

此設置方法也爲您的屬性賦值並提高屬性更改事件 –

+0

我明白了,但是我想要運行一個方法,如果值更改爲像這樣'if(_highDwellDiameter!= value){_highDwellDiameter = value; highDwellRadius = value/2; RaisePropertyChanged(); }' – Adam