2010-03-13 42 views
4

我有一些邏輯取決於兩個屬性被設置,因爲它執行時,兩個屬性都有一個值。例如:如何處理MVVM ViewModel中的「SelectedItemChanged」事件?

private void DoCalc() { 
    if (string.IsNullOrEmpty(Property1) || string.IsNullOrEmpty(Property2)) 
    return; 
    Property3 = Property1 + " " + Property2; 
} 

該代碼將需要每次Property1或Property2改爲執行,但我無法弄清楚如何做到這一點的風格上可以接受的方式。下面是選擇,因爲我看到他們:

1)從視圖模型

調用方法

我沒有這個概念有問題,因爲邏輯仍然是在視圖模型 - 我不是一個「不代碼隱藏「納粹。然而,'觸發'邏輯(當任何一個屬性發生變化時)仍然在UI層,我不喜歡。代碼隱藏應該是這樣的:

void ComboBox_Property1_SelectedItemChanged(object sender, RoutedEventArgs e) { 
    viewModel.DoCalc(); 
} 

2)從屬性setter

調用方法這種方法似乎是最「純」,但它似乎也難看,彷彿邏輯是隱藏的。它應該是這樣的:

public string Property1 { 
    get {return property1;} 
    set { 
    if (property1 != value) { 
     property1 = value; 
     NotifyPropertyChanged("Property1"); 
     DoCalc(); 
    } 
    } 
} 

3)掛接到PropertyChanged事件

現在,我想這可能是正確的做法,但感覺怪異掛接到在實施屬性更改事件視圖模型。這將是這個樣子:

public ViewModel() { 
    this.PropertyChanged += new PropertyChangedEventHandler(ViewModel_PropertyChanged); 
} 

void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) { 
    if (e.PropertyName == "Property1" || e.PropertyName == "Property2") { 
    DoCalc(); 
    } 
} 

所以,我的問題是,如果你是通過與這一要求,你更喜歡哪一種方法,看看實施的一些源代碼瀏覽(爲什麼?)。感謝您的任何意見。

回答

3

我不認爲在setter中這樣做很醜陋......實際上它可能是你提到的3種方法中最好的,因爲當你閱讀代碼時,你立即看到改變Property1Property2的值將會重新計算Property3;這與其他兩種方法完全不同。

但是,我不會使用這些選項。我覺得這樣做的更好的辦法是使Property3只讀,並計算其在吸氣值,根據Property1Property2

public string Property3 
{ 
    get { return Property3 = Property1 + " " + Property2; } 
} 

這樣一來,在Property1Property2的制定者,你只要還需要撥打NotifyPropertyChanged以獲取Property3

+1

除非第三屬性是小事就像在你的榜樣,二傳手'Property1'和'Property2'也應該設置一些'IsProperty3Invalid'標誌,這對於'Property3'吸氣會檢查看看是否需要再次調用「DoCalc」。 – Gabe

+0

這是一個有趣的想法(我顯然沒有考慮過)。我不得不考慮這個問題,因爲在'真實'代碼中,屬性3有時由prop1和prop2設置,但如果它不是由這些條件設置的,則用戶必須手動填寫它。可以使用這種方法來完成......我會對其進行編碼並查看它的外觀。好東西。 – Travis

+0

標記爲正確的,只是給你一些道具,但不知道我100%同意。需要浸泡在它:)。 – Travis

0

是@Thomas是對的。方法2是進入WPF環境的完美方式。假設您已將ListBox.SelectedValue TwoWay綁定到Property1

您的(1)無效,因爲它將業務邏輯暴露給View。 (3)是一個不必要的事件處理,無論如何都是由Property1設置程序代碼觸發的。所以最好直接從Setter中調用它。所以MVVM的方式是(2)

1

(2)是我平常的做法。

這就是說,它讓我想知道是否有可能是另一種方式使用的Rx框架做這種類型的事情:http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx

原來這就是我想出了(警告 - 不要做這種方式);!)

public class ViewModel : INotifyPropertyChanged 
{ 
    public ViewModel() 
    { 
     var o1 = 
      Observable.FromEvent<PropertyChangedEventArgs>(this, "PropertyChanged"); 
     o1.Subscribe(e => Debug.WriteLine(e.EventArgs.PropertyName)); 
     var o2 = o1.SkipWhile(e => e.EventArgs.PropertyName != "Property1"); 
     var o3 = o1.SkipWhile(e => e.EventArgs.PropertyName != "Property2"); 
     var o4 = o1.SkipWhile(e => e.EventArgs.PropertyName != "Result"); 
     var o5 = Observable.CombineLatest(o2, o3, (e1, e2) => DoStuff()).TakeUntil(o4); 
     o5.Subscribe(o => Debug.WriteLine("Got Prop1 and Prop2")); 
    } 

    public string DoStuff() 
    { 
     return Result = string.Concat(Property1, Property2);     
    } 

    private string _property1; 
    public string Property1 
    { 
     get { return _property1; } 
     set 
     { 
      _property1 = value; 
      OnNotifyPropertyChanged("Property1"); 
     } 
    } 
    private string _property2; 
    public string Property2 
    { 
     get { return _property2; } 
     set 
     { 
      _property2 = value; 
      OnNotifyPropertyChanged("Property2"); 
     } 
    } 
    private string _result; 
    public string Result 
    { 
     get { return _result; } 
     set 
     { 
      _result = value; 
      OnNotifyPropertyChanged("Result"); 
     } 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 
    private void OnNotifyPropertyChanged(string name) 
    { 
     var handler = PropertyChanged; 
     if(handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
} 
+0

有趣。我不會那樣做;-) – Travis

相關問題