2012-05-04 31 views
8

也許這裏已經是這樣的問題,但我沒有找到它。在setter中自訂的PropertyChanged或添加方法調用?

我有MVVM應用程序,在我的ViewModel我必須做一些更改某些屬性的其他操作(例如,如果View更改它們)。你認爲哪種方法更好,爲什麼?

1日 - 添加AdditionalAction呼叫設定器

public class ViewModel: INotifyPropertyChanged 
{ 
    private int _MyProperty; 

    public int MyProperty 
    { 
    get { return _MyProperty; } 
    set 
    { 
     if (_MyProperty == value) return; 
     _MyProperty = value; 
     RaisePropertyChanged(() => MyProperty); 

     // --- ADDITIONAL CODE --- 
     AdditionalAction(); 
    } 
    } 
} 

2日 - 自訂閱INotifyPropertyChanged的

public class ViewModel: INotifyPropertyChanged 
{ 
    public ViewModel() 
    { 
    // --- ADDITIONAL CODE --- 
    PropertyChanged += OnPropertyChanged; 
    } 

    private int _MyProperty; 

    public int MyProperty 
    { 
    get { return _MyProperty; } 
    set 
    { 
     if (_MyProperty == value) return; 
     _MyProperty = value; 
     RaisePropertyChanged(() => MyProperty); 
    } 
    } 

    void PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
    // --- ADDITIONAL CODE --- 
    if (e.PropertyName == "MyProperty") 
     AdditionalAction(); 
    } 
} 

想象一下,我沒有性能問題或10'000個物體。這只是View和ViewModel。什麼是更好的?第一個代碼是「更小」,開銷更少,但第二個代碼更清晰,我可以使用代碼片段來自動生成代碼。甚至更多 - 在第二個情況下,我可以在事件處理程序像寫:

On.PropertyChanged(e, p => p.MyProperty, AdditionalAction); 

其中On類是輔助性。

那麼,你心目中的什麼更好,爲什麼?

更新:

OK,它看起來像我發現還沒有一種方法:

3日 - 在RaisePropertyChanged加上 「擴展點」:

public class NotificationObject : INotifyPropertyChanged 
{ 
    void RaisePropertyChanged(Expression<...> property) 
    { 
    // ... Raise PropertyChanged event 
    if (PropertyChanged != null) 
     // blah-blah 

    // Call extension point 
    OnPropertyChanged(property.Name); 
    } 

    public virtual OnPropertyChanged(string propertyName) 
    { 
    } 
} 

public class ViewModel: NotificationObject 
{ 
    private int _MyProperty; 

    public int MyProperty 
    { 
    get { return _MyProperty; } 
    set 
    { 
     if (_MyProperty == value) return; 
     _MyProperty = value; 
     RaisePropertyChanged(() => MyProperty); 
    } 
    } 

    override OnPropertyChanged(string propertyName) 
    { 
    if (propertyName == "MyProperty") 
     AdditionalAction(); 
    } 
} 

這樣我們不使用事件,但所有「附加動作」都是從相同的「擴展點」調用的。是「所有添加行爲的一個地方」比「不透明的工作流程」更好嗎?

+2

http://tergiver.wordpress.com/2011/01/20/self-subscription-is-asinine/ – Tergiver

+0

旁註:考慮使用一個輔助方法把你的屬性的setter三線之一,如果屬性確實改變,則返回一個布爾值。更短,沒有重複。例如'if(RaisePropertyChanged(ref _MyProperty,value,o => o.MyProperty))AdditionalAction();' – stijn

+0

@Tergiver你的方式和我的第二種方式有什麼不同?它們是相同的 - 你不在「setter」中編寫額外的代碼,而是在「事件處理程序」中編寫 - 從這個角度來看,「OnXXX」方法與自定義事件相同。所以,從你的角度來看,我的問題是 - 「從setter或OnPropertyChanged方法調用'AdditionalAction'更好嗎?」 (即使實際上沒有方法OnPropertyChanged) – chopikadze

回答

3

肯定去的第一種方法:

  • 很明顯
  • 它在它的流量和意向明確
  • 它避免怪異(IMO)自認購

第二個「好處」,可讓您使用自動生成的屬性,不值得執行流程的清晰度的冷杉案件,伊莫。

希望這會有所幫助。

+0

你對第三種方式有什麼看法? – chopikadze

+0

@chopikadze:看起來不錯,因爲它*可以*支持重構代碼,如果你以某種方式擺脫字符串:propertyName。 – Tigran

3

這是「常用」模式。這允許您將屬性特定的代碼放入OnX方法中,並允許派生類執行相同的操作。不需要一個大的switch語句,除非你是外部監聽者,但是這對於INotifyPropertyChanged來說是相同的。

public class NotificationObject : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    protected void FirePropertyChanged(PropertyChangedEventArgs e) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
      handler(this, e); 
    } 
} 

public class ViewModel : NotificationObject 
{ 
    private int _MyProperty1; 
    public int MyProperty1 
    { 
     get { return _MyProperty1; } 
     set 
     { 
      if (value != _MyProperty1) 
      { 
       _MyProperty1 = value; 
       OnMyProperty1Changed(new PropertyChangedEventArgs("MyProperty1")); 
      } 
     } 
    } 

    protected virtual void OnMyProperty1Changed(PropertyChangedEventArgs e) 
    { 
     FirePropertyChanged(e); 
    } 

    private int _MyProperty2; 
    public int MyProperty2 
    { 
     get { return _MyProperty2; } 
     set 
     { 
      if (value != _MyProperty2) 
      { 
       _MyProperty2 = value; 
       OnMyProperty2Changed(new PropertyChangedEventArgs("MyProperty2")); 
      } 
     } 
    } 

    protected virtual void OnMyProperty2Changed(PropertyChangedEventArgs e) 
    { 
     FirePropertyChanged(e); 
    } 
} 
+0

非常感謝您的幫助,我標記@Tigran的答案僅僅是因爲它擁有更多的選票,但我真的很感謝我們的討論! – chopikadze