【问题标题】:How can I handle a Validation.Error in my ViewModel instead of my View's code behind?如何处理 ViewModel 中的 Validation.Error 而不是 View 背后的代码?
【发布时间】:2010-10-29 15:02:53
【问题描述】:

我正在尝试让 WPF 验证在 MVVM 模式中工作。

在我的视图中,我可以验证这样的文本框,它由代码隐藏方法“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>

但是,我想通过 DelegateCommand 在我的 ViewModel 中处理验证,但是当我尝试使用以下代码时,我得到了显式错误“'{Binding HandleErrorCommand}' is not a valid event handler method名称。只有生成类或代码隐藏类上的实例方法才有效。"

是否有任何解决方法,以便我们可以在 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

【问题讨论】:

    标签: c# wpf validation mvvm


    【解决方案1】:

    这是一种使用 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>
    

    ViewModel:(可以保持不变,但这里看看我在使用异常验证规则时如何挖掘验证参数以找到错误消息)

        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;
        }
    

    ValidationErrorEventTrigger:

    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;
        }
    }
    

    【讨论】:

    • 谢谢,效果很好!我只需更改一点 XAML 即可使用 MVVM Light 注册事件: MVVMBehaviors:ValidationErrorEventTrigger>
    • 谢谢,下面的代码对我有用
    【解决方案2】:

    我不知道这是否会对您有所帮助,但我会提供相同的。

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

    我没有在我的视图中指定任何验证,无论是在后面的代码中还是在 xaml 中。我的视图只有数据绑定到 ViewModel 上的属性。

    我所有的错误检查/验证都由 ViewModel 处理。当我遇到错误时,我设置了一个 ErrorMessage 属性,该属性也绑定到视图。 ErrorMessage 文本块(在视图中)有一个值转换器,如果错误为 null 或为空,它将隐藏它。

    以这种方式做事可以很容易地对输入验证进行单元测试。

    【讨论】:

    • 很高兴知道,这是我将要采取的方向,因为 WPF 中的验证目前看起来不像我想象的那么简单或功能齐全。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 2019-06-24
    • 2019-01-01
    相关资源
    最近更新 更多