2009-05-28 60 views
4

我試圖讓WPF驗證在MVVM模式中工作。如何處理ViewModel中的Validation.Error而不是View的代碼?

在我看來,我可以驗證一個TextBox這樣它獲取的代碼隱藏方法「的HandleError」,它工作正常辦理:

<TextBox Width="200" 
     Validation.Error="HandleError"> 
    <TextBox.Text> 
     <Binding Path="FirstName" 
      NotifyOnValidationError="True" 
      Mode="TwoWay"> 
      <Binding.ValidationRules> 
       <validators:DataTypeLineIsValid/> 
      </Binding.ValidationRules> 
     </Binding> 
    </TextBox.Text> 
</TextBox> 

不過,我想辦理驗證我的ViewModel通過一個DelegateCommand,但是當我用下面的代碼嘗試它時,我得到了顯式錯誤「'{Binding HandleErrorCommand}'不是一個有效的事件處理程序方法名,只有生成的或代碼隱藏類的實例方法纔有效。

是否有任何解決方法,以便我們可以處理MVVM模式中的驗證?

查看:

<TextBox Width="200" 
     Validation.Error="{Binding HandleErrorCommand}"> 
    <TextBox.Text> 
     <Binding Path="FirstName" 
      NotifyOnValidationError="True" 
      Mode="TwoWay"> 
      <Binding.ValidationRules> 
       <validators:DataTypeLineIsValid/> 
      </Binding.ValidationRules> 
     </Binding> 
    </TextBox.Text> 
</TextBox> 

視圖模型:

#region DelegateCommand: HandleError 
private DelegateCommand handleErrorCommand; 

public ICommand HandleErrorCommand 
{ 
    get 
    { 
     if (handleErrorCommand == null) 
     { 
      handleErrorCommand = new DelegateCommand(HandleError, CanHandleError); 
     } 
     return handleErrorCommand; 
    } 
} 

private void HandleError() 
{ 
    MessageBox.Show("in view model"); 
} 

private bool CanHandleError() 
{ 
    return true; 
} 
#endregion 

回答

9

我不知道這是否會對您有所幫助,但我會提供一切。

此外,我使用的是Silverlight,而不是WPF。

我沒有在我的視圖中指定任何驗證,在後面的代碼和xaml中都沒有。我的視圖只有數據綁定到ViewModel上的屬性。

我所有的錯誤檢查/驗證都由ViewModel處理。當我遇到錯誤時,我設置了一個ErrorMessage屬性,該屬性也綁定到視圖。 ErrorMessage文本塊(在視圖中)有一個值轉換器,如果錯誤爲空或空,它將隱藏它。

這樣做的事情可以很容易地單元測試輸入驗證。

+0

很高興知道,這是我要帶,因爲在WPF驗證目前似乎並沒有那樣直接或功能全,因爲我認爲這將是方向。 – 2009-05-29 07:54:00

0

活動有貓膩與MVVM,但並非不可能。典型的方法是使用附加的行爲來處理這個問題。 Caliburn在Message.Attach行爲中有一個可用的解決方案。

6

以下是使用Expression Blend 3行爲執行此操作的一種方法。我寫了一個ValidationErrorEventTrigger,因爲內置的EventTrigger不適用於附加的事件。

查看:

<TextBox> 
<i:Interaction.Triggers> 
    <MVVMBehaviors:ValidationErrorEventTrigger> 
     <MVVMBehaviors:ExecuteCommandAction TargetCommand="HandleErrorCommand" /> 
    </MVVMBehaviors:ValidationErrorEventTrigger> 
</i:Interaction.Triggers> 
<TextBox.Text> 
    <Binding Path="FirstName" 
      Mode="TwoWay" 
      NotifyOnValidationError="True"> 
     <Binding.ValidationRules> 
      <ExceptionValidationRule /> 
     </Binding.ValidationRules> 
    </Binding> 
</TextBox.Text> 

視圖模型:(可能是不變的,但這裏有一個看看我是怎麼挖成的驗證參數查找錯誤消息中的異常驗證時規則)

public ICommand HandleErrorCommand 
    { 
     get 
     { 
      if (_handleErrorCommand == null) 
       _handleErrorCommand = new RelayCommand<object>(param => OnDisplayError(param)); 
      return _handleErrorCommand; 
     } 
    } 

    private void OnDisplayError(object param) 
    { 
     string message = "Error!"; 
     var errorArgs = param as ValidationErrorEventArgs; 
     if (errorArgs != null) 
     { 
      var exception = errorArgs.Error.Exception; 
      while (exception != null) 
      { 
       message = exception.Message; 
       exception = exception.InnerException; 
      } 
     } 
     Status = message; 
    } 

Validati onErrorEventTrigger:

public class ValidationErrorEventTrigger : EventTriggerBase<DependencyObject> 
{ 
    protected override void OnAttached() 
    { 
     Behavior behavior = base.AssociatedObject as Behavior; 
     FrameworkElement associatedElement = base.AssociatedObject as FrameworkElement; 

     if (behavior != null) 
     { 
      associatedElement = ((IAttachedObject)behavior).AssociatedObject as FrameworkElement; 
     } 
     if (associatedElement == null) 
     { 
      throw new ArgumentException("Validation Error Event trigger can only be associated to framework elements"); 
     } 
     associatedElement.AddHandler(Validation.ErrorEvent, new RoutedEventHandler(this.OnValidationError)); 
    } 
    void OnValidationError(object sender, RoutedEventArgs args) 
    { 
     base.OnEvent(args); 
    } 
    protected override string GetEventName() 
    { 
     return Validation.ErrorEvent.Name; 
    } 
} 
+1

謝謝,它工作得很好!我只需要稍微改變一下XAML以使用MVVM Light註冊事件: 2013-06-10 16:11:49

相關問題