2009-05-28 63 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

相关问题