2011-11-03 35 views
12

我知道MVVM大量使用INotifyPropertyChanged,但我從未見過INotifyPropertyChanging的任何用法。任何理由?爲什麼沒有人使用INotifyPropertyChanging?

如果我想用這個,這將是該融入我的MVVM框架的好辦法?我知道你不應該在ViewModel上使用MessageBox,因爲那樣你就無法對它進行單元測試。那麼如何才能拋出警報,然後繼續使用PropertyChange(如果適用)?

+1

你想在這裏實現什麼?知道什麼時候房產是*關於*改變的用例是什麼? – ChrisF

+0

驗證用戶「你確定嗎?」對於某些更改......我們希望確保管理員意味着更改用戶的用戶名/登錄名,並且他們不會意外更新該字段。 – michael

回答

11

需要記住的事項INotifyPropertyChanging是你不能停止從發生的變化。這隻允許您記錄發生的變化。

我用它在我的更改跟蹤的框架,但它不是停止變化的適當方法。

你可以使用自定義接口/事件對延長您的ViewModelBase

delegate void AcceptPendingChangeHandler(
    object sender, 
    AcceptPendingChangeEventArgs e); 

interface IAcceptPendingChange 
{ 
    AcceptPendingChangeHandler PendingChange; 
} 

class AcceptPendingChangeEventArgs : EventArgs 
{ 
    public string PropertyName { get; private set; } 
    public object NewValue { get; private set; } 
    public bool CancelPendingChange { get; set; } 
    // flesh this puppy out 
} 

class ViewModelBase : IAcceptPendingChange, ... 
{ 
    protected virtual bool RaiseAcceptPendingChange(
     string propertyName, 
     object newValue) 
    { 
     var e = new AcceptPendingChangeEventArgs(propertyName, newValue) 
     var handler = this.PendingChange; 
     if (null != handler) 
     { 
      handler(this, e); 
     } 

     return !e.CancelPendingChange; 
    } 
} 

此時你需要按照慣例將它添加到您的視圖模型:

class SomeViewModel : ViewModelBase 
{ 
    public string Foo 
    { 
     get { return this.foo; } 
     set 
     { 
      if (this.RaiseAcceptPendingChange("Foo", value)) 
      { 
       this.RaiseNotifyPropertyChanging("Foo"); 
       this.foo = value; 
       this.RaiseNotifyPropretyChanged("Foo"); 
      } 
     } 
    } 
} 
1

要回答第二個問題,你總是可以使用依賴注入模式,讓您的虛擬機依賴的接口(INotifier?)上,並通過一個具體的實施會彈出消息框。這使單元測試性保持不變。

編輯: 第一個問題可能是這麼過於主觀。界面的意圖很明確,但何時使用它將用於非常具體的用例。依賴屬性引發了類似的情況,在應用它之前檢查新值是有效的,但如果使用簡單屬性,則可以更簡單地將此檢查放入設置器中。如果不同的組件需要檢查有效性,那麼如果該組件自己(在驗證新值之後)進行更改,或者被顯式調用以驗證由進行更改的組件進行的更改,則通常會更簡單。

-6

您需要INotifyPropertyChanged例如,如果你想知道什麼時候任何變量將被改變,因爲你可以使用PropertyChangedEventHandler。 通過這種方式,您可以在運行程序時重新加載gui,如果有任何依賴屬性綁定在任何gui元素上。

對於最後一個問題,我想你可以寫一個日誌文件與你定義的消息,如果你想顯示給用戶的任何警報,您可以使用類似的錯誤總結或提示控件。但是,如果您只需要進行測試,則可以使用try和catch塊保留警報。

+1

OP詢問'INotifyPropertyChanging'接口,而不是'INotifyPropertyChanged' –

+1

忽略錯誤接口的無辜錯誤,在本場景中鑽入日誌文件並嘗試/捕獲不存在的屬性驗證異常不是很好的建議。 – JRoughan

1

INotifyPropertyChanging在屬性更改之前被調用。重要原因?所以外部事件處理程序可以拋出異常並阻止更改。你爲什麼要這麼做?有一天它可能是你在別人的代碼庫中的一個錯誤的唯一解決方法,所以不要那麼快地刪除逃生艙口。

+5

在事件處理程序中拋出一個異常來結束事件執行時,firer會引起我的巨大代碼嗅覺,包括執行此操作的選項*以防萬一使我感覺更糟。 –

3

INotifyPropertyChanging是使用LINQ到使用SQL優化。當一個對象實現這個接口時,它使用改變事件作爲緩存屬性的舊值的信號。如果對象沒有實現這個接口,那麼它總是會緩存屬性值,從而增加內存使用量。 有關更多詳細信息,請參閱How does INotifyPropertyChanging interface helps limit memory consumption

相關問題