【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();
    }
}

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

效果

相关推荐
阿湯哥15 小时前
多智能体架构深度解析:企业落地如何选择Skills与SubAgents?
架构·wpf
源之缘-OFD先行者15 小时前
自研 WPF 鸟情图表:性能与灵活的双重突破
wpf
Moqiqiuzi15 小时前
WPF单实例启动
wpf
Moqiqiuzi15 小时前
WPF程序打包成安装包的方法
wpf
码农水水1 天前
国家电网Java面试被问:TCP的BBR拥塞控制算法原理
java·开发语言·网络·分布式·面试·wpf
码农水水1 天前
京东Java面试被问:HTTP/2的多路复用和头部压缩实现
java·开发语言·分布式·http·面试·php·wpf
闻缺陷则喜何志丹2 天前
【C# WPF】TextBox的数据绑定
ui·c#·wpf·mvvm·数据绑定·textbox
码农水水3 天前
得物Java面试被问:大规模数据的分布式排序和聚合
java·开发语言·spring boot·分布式·面试·php·wpf
时光慢煮3 天前
行走在多端之间:基于 Flutter × OpenHarmony 的旅行记录应用实践 —— 旅行详情查看模块解析
flutter·华为·开源·wpf·openharmony
xiaobaishuoAI3 天前
分布式事务实战(Seata 版):解决分布式系统数据一致性问题(含代码教学)
大数据·人工智能·分布式·深度学习·wpf·geo