2013-10-17 27 views
0

我正在使用MVVM模式的WPF。異步/等待在INotifyPropertyChanging EventHandler與可取消EventArgs

在我的模型類中,我使用從PropertyChangingEventArgs派生的自定義EventArgs實現了INotifyPropertyChanging接口。這是必要的,因爲我想能夠「取消」屬性設置器。

該事件正在包含該模型的ViewModel中處理。

在事件處理程序中,我必須調用數據庫,並根據結果有時必須通過事件參數取消屬性設置器。

模型類似於如下:

public class CancellablePropertyChangingEventArgs : PropertyChangingEventArgs 
{ 
    public bool Cancel { get; set; } 
} 

public class Model : INotifyPropertyChanging 
{ 
    public string MyProperty 
    { 
     get { return _myProperty; } 
     set 
     { 
      var args = RaisePropertyChanging(); 

      if(!args.Cancel) 
       _myProperty = value; 
     } 
    } 

    public CancellablePropertyChangingEventArgs RaisePropertyChanging([CallerMemberName] string propertyName = "") 
    { 
     var eventArgs = new CancellablePropertyChangingEventArgs(propertyName); 
     if(PropertyChanging != null) 
     { 
      PropertyChanging(this, eventArgs); 
     } 

     return eventArgs; 
    } 
} 

其中包含了上述模型和處理PropertyChanging事件,在事件處理程序我有一個類似的代碼視圖模型:

private async void HandleModelPropertyChanging(object sender, PropertyChangingEventArgs e) 
{ 
    var args = e as CancellablePropertyChangingEventArgs; 

    if(args.PropertyName = "MyProperty") 
    { 
     var result = await CallToDataBaseAsync(...); 
     if(result == null) 
      args.Cancel = true; 
    } 

}

我知道在我的事件處理程序中的異步無效意味着「火與忘」和t因此事件處理程序繼續在CallToDataBaseAsync上執行,而不是等待它,所以args.Cancel將始終爲假。

但是有沒有其他可能的解決方案,我可以嘗試,而不阻止GUI線程?

+4

安裝人員取消不是一個正確的方法。允許用戶輸入無效數據,然後運行驗證並顯示錯誤。 – Dennis

+2

你是否會用值驗證來混淆「setter cancellation」?由於外部事件(數據庫查詢)而取消setter是錯誤的。拒絕一個新值是因爲它沒有通過數據庫的驗證,這更有意義,並且受到Binding.ValidationRules,IDataErrorInfo等機制的支持。 –

回答

3

我以前走過這條路 - 取消setter是錯誤的方法,它不會像你期望的那樣工作,甚至等待。設置此屬性的wpf綁定需要您更改屬性或引發異常作爲驗證機制。所以簡單的取消不分配值並且不解僱PropertyChanged事件將導致您的控件失步,即設置此屬性 - 它將顯示用戶鍵入的數據,而不是實際存儲在屬性中的數據。

如果你真的想試試它,無論如何改變你的處理程序返回任務,但要記住,這是有缺陷的解決方案 - 如果你有多個處理程序連接只有最後一個的結果將被等待。通過一些更多的工作,你可以將這些任務集合起來,但無論如何都是沒有意義的