【WPF】使用Behavior以及ValidationRule实现表单校验

文章目录

使用ValidationRule实现检测用户输入

EmptyValidationRule是TextBox内容是否为空校验,TextBox的Binding属性设置ValidationRule后,TextBox将自带校验红框效果。但是默认是没有报错提示的。需要开启验证错误的通知属性 NotifyOnValidationError,这样可以通过绑定 Validation.Error 事件处理程序获取到Message进行提示

EmptyValidationRule 非空校验

csharp 复制代码
public class EmptyValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        string str = value as string;
        if (string.IsNullOrWhiteSpace(str))
        {
            return new ValidationResult(false, "不能为空,输入有效值");
        }
        return ValidationResult.ValidResult;
    }
}

TextBox设置非空校验

UpdateSourceTrigger="PropertyChanged" 设置每次输入都触发双向绑定,Binding.ValidationRules 设置校验逻辑
ValidatesOnTargetUpdated="True" 设置 首次加载就校验(默认启动程序的时候不开启校验,当你第一次输入才校验)

xml 复制代码
<StackPanel
    Grid.Row="1"
    HorizontalAlignment="Center"
    Orientation="Horizontal">
    <TextBlock VerticalAlignment="Center" Text="年龄:" />
    <TextBox
        Width="200"
        Height="30"
        Margin="10,0"
        VerticalAlignment="Center"
        VerticalContentAlignment="Center">
        <TextBox.Text>
            <Binding Path="Age" UpdateSourceTrigger="PropertyChanged">
                <Binding.ValidationRules>
                    <Valid:EmptyValidationRule ValidatesOnTargetUpdated="True" />
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>
</StackPanel>


TextBox设置非空校验并显示校验提示

按照上述说明的【需要开启验证错误的通知属性 NotifyOnValidationError,这样可以通过绑定 Validation.Error 事件处理程序获取到Message进行提示】

这边采用的是WPF的行为Behavior。
IValidationExceptionHandler ,输入校验接口,需要进行校验的页面的ViewModel需要继承并实现他的两个属性IsValid 以及

Message

csharp 复制代码
/// <summary>
/// 输入校验接口
/// </summary>
public interface IValidationExceptionHandler
{
    /// <summary>
    /// 是否有校验异常
    /// </summary>
    bool IsValid { get; set; }

    /// <summary>
    /// 异常提示
    /// </summary>
    string Message { get; set; }
}
  1. 首先先定义一个行为 ValidationExceptionBehavior
cs 复制代码
public class ValidationExceptionBehavior : Behavior<FrameworkElement>
{

    // 实现你的行为逻辑
    protected override void OnAttached()
    {
        // 在此处理附加逻辑
        // AssociatedObject 就是 行为的对象 FrameworkElement
        AssociatedObject.AddHandler(Validation.ErrorEvent, new EventHandler<ValidationErrorEventArgs>(OnValidationError));
    }

    protected override void OnDetaching()
    {
        // 在此处理分离逻辑
        //移除 Validation.Error 事件监听
        this.AssociatedObject.RemoveHandler(Validation.ErrorEvent, new EventHandler<ValidationErrorEventArgs>(OnValidationError));
    }

    private void OnValidationError(object sender, ValidationErrorEventArgs e)
    {
        IValidationExceptionHandler validationException = null;
        if (AssociatedObject.DataContext is IValidationExceptionHandler)
        {
            validationException = this.AssociatedObject.DataContext as IValidationExceptionHandler;
        }
        if (validationException == null) return;
        
        //OriginalSource 触发事件的元素
        var element = e.OriginalSource as UIElement;
        if (element == null) return;

        //ValidationErrorEventAction.Added  表示新产生的行为
        if (e.Action == ValidationErrorEventAction.Added)
        {
            // EmptyValidationRule返回的结果字符串
            validationException.IsValid = true;
            string error = e.Error.ErrorContent.ToString();

            validationException.Message = error;
        }
        else if (e.Action == ValidationErrorEventAction.Removed) //ValidationErrorEventAction.Removed  该行为被移除,即代表验证通过
        {
            validationException.IsValid = false;
            validationException.Message = string.Empty;
        }
    }

    
}
  1. TextBox的Binding属性中的NotifyOnValidationError="True",开启验证错误的通知属性,产生 Validation.Error 事件。
xml 复制代码
<StackPanel
    Grid.Row="1"
    HorizontalAlignment="Center"
    Orientation="Horizontal">
    <TextBlock VerticalAlignment="Center" Text="年龄:" />
    <TextBox
        Width="200"
        Height="30"
        Margin="10,0"
        VerticalAlignment="Center"
        VerticalContentAlignment="Center">
        <TextBox.Text>
        <!--  开启验证错误的通知属性 NotifyOnValidationError="True" 。这样就可以产生 Validation.Error 事件  -->
            <Binding
                NotifyOnValidationError="True"
                Path="Age"
                UpdateSourceTrigger="PropertyChanged">
                <Binding.ValidationRules>
                <!--  ValidatesOnTargetUpdated="True" 首次加载就校验  -->
                    <Valid:EmptyValidationRule ValidatesOnTargetUpdated="True" />
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>
    <!--  显示校验异常内容  -->
    <Label
        MinWidth="100"
        VerticalAlignment="Center"
        VerticalContentAlignment="Center"
        Content="{Binding Message}"
        FontSize="15"
        Foreground="Red" />
</StackPanel>
  1. 绑定行为
    引入命名空间 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    绑定行为
xml 复制代码
<i:Interaction.Behaviors>
    <Valid:ValidationExceptionBehavior />
</i:Interaction.Behaviors>

效果


结语

校验异常可以有多种展现形式和方法。

可以在提交按钮时候,判断异常字符串是否为空,不为空弹窗。

可以行为中使用GalaSoft.MvvmLight中的Messenger进行发布订阅(注册消费)。

例如下面这样

当Message被赋值时,会触发 Messenger.Default.Send

ViewModol中

cs 复制代码
private string _message;

/// <summary>
/// 实现 IValidationExceptionHandler的成员Message
/// </summary>
public string Message
{
    get { return _message; }
    set
    {
        _message = value;
        if (!string.IsNullOrWhiteSpace(_message))
        {
            // 发送消息
            Messenger.Default.Send<string, MainView>(_message);
        }

        RaisePropertyChanged();
    }
}

在页面初始化时注册弹窗事件

效果

相关推荐
就是有点傻10 小时前
C#中面试的常见问题004
面试·职场和发展·c#·wpf
martian66512 小时前
C# 开发应用篇——C# 基于WPF实现数据记录导出excel详解
c#·wpf·excel
就是有点傻1 天前
C#中面试的常见问题005
开发语言·面试·c#·wpf
gjhaoiaao1 天前
《白帽子讲Web安全》13-14章
安全·web安全·php·wpf
就是有点傻1 天前
WPF中的Button按钮中的PreviewMouseLeftButtonDown事件和MouseLeftButtonDown的区别
c#·wpf
海的那边-1 天前
WPF 加载页面的三种方式(瞬时加载,延迟加载,异步行为)
wpf
lfw20191 天前
WPF ItemsControl控件
wpf
就是有点傻1 天前
C#中面试的常见问题007
面试·c#·wpf
就是有点傻2 天前
C#中面试的常见问题006
开发语言·面试·c#·wpf
就是有点傻2 天前
WPF中如何让Textbox显示为一条直线
c#·wpf