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

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

效果

相关推荐
慧都小妮子17 小时前
SciChart WPF v9.0 更新详解:矢量场图表、堆叠箱线图与 MVVM 轴同步来了
c#·.net·wpf·数据可视化·图表控件·图表
He BianGu1 天前
【笔记】WPF中 Brush 的类型、继承关系、使用方式和注意事项
笔记·wpf
FuckPatience3 天前
WPF GridView 列绑定时前端没有属性提示
wpf
界面开发小八哥3 天前
界面控件DevExpress WPF v26.1新版亮点 - 模板工具包 & MVVM功能全新升级
wpf·界面控件·devexpress·ui开发·.net 10
记忆停留w5 天前
Celery+Redis 分布式异步任务队列工程落地业务逻辑
大数据·人工智能·redis·分布式·缓存·架构·wpf
雪靡5 天前
WPF PerMonitorV2 下的跨窗口问题
c#·wpf
listening7776 天前
HarmonyOS 6.1 分布式文件服务实战:跨设备商品图片/视频秒开方案
wpf·harmonyos
Macbethad6 天前
基于WPF的半导体设备EAP控制程序架构设计与实现
wpf
国服第二切图仔7 天前
HarmonyOS APP《画伴梦工厂》开发第60篇-分布式软总线2.0——多设备协同新范式
分布式·wpf·harmonyos
精神底层7 天前
拒绝 UI 卡死!我用 CSnakes 实时拦截 Python 训练流,在 WPF 中重构了 ScottPlot 5 高性能 AI 看板
python·ui·wpf