WINUI——自定义验证特性

背景

在开发过程中验证数据是否符合要求是经常遇到的,如IP的验证、邮箱的验证、电话号码的验证等等。C#中System.ComponentModel.DataAnnotations 命名空间下提供了一些常用特性用于数据的验证,常用的如Required、MaxLength、MinLength、Key、NotMapped等等,满足了多数时候的使用需求,但对于一些场景,还不能满足项目需要的。这时就需要自定义相应的验证特性,以满足工程需要。

开发环境

WIN11

VS2022

MVVM Toolkit7.1.2

.net core6

自定义验证特性

自定义方法如下

  1. 添加AttributeUsage特性。
  2. 继承于ValidationAttribute,重写IsValid方法。

以自定义端口验证特性进行详细的说明:

cs 复制代码
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class PortNumberAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null)
        {
            return new ValidationResult("端口号不能为空");
        }

        var portString = value.ToString();

        if (!int.TryParse(portString, out int port))
        {
            return new ValidationResult("请输入有效的端口号");
        }

        if (port < 0 || port > 65535)
        {
            return new ValidationResult("端口号必须在0到65535之间");
        }

        // 可以在这里检查端口是否已被使用等  

        return ValidationResult.Success;
    }
}

注意:

AttributeUsage中添加了AttributeTargets.Property,它指此验证特性可用于Property(属性)上;

AllowMultiple = false 表示在同一属性上不可多次使用此自定义验证特性;

Inherited = true 表示这个验证特性是可以继承的。

VM使用如下

使用方法如下(以下代码使用了MVVM Toolkit,整个VM继承于它的ObservableValidator以进行数据验证,因此SetProperty与GetErrors可直接使用):

cs 复制代码
        [ObservableProperty]
        private string localPortErrorMessage;
        [PortNumber(ErrorMessage = "请输入有效的端口号")]
        public string LocalTerminalPort
        {
            get => localTerminalPort;
            set
            {
                SetProperty(ref localTerminalPort, value, true);
                LocalPortErrorMessage = GetErrors(nameof(LocalTerminalPort)).Cast<ValidationResult>().FirstOrDefault()?.ErrorMessage ?? string.Empty;
            }
        }

上述代码中的LocalPortErrorMessage即是出错的报错信息,绑定此信息到xaml上,填写出错时即可及时看到出错信息。

在VM中若有多个验证的情况下,一个不满足时就不请允许进行后续操作,这时可利用ObservableValidator 提供的**HasErrors**进行相应判断。

x:Bind属性注意事项

xaml中绑定时需要注意,由于验证特性是在set时进行验证,然后设置相应的错误信息,也就是说需要验证的属性变化时就要立马验证,如果使用x:Bind进行验证时,则需要设置Mode=TwoWay且UpdateSourceTrigger=PropertyChanged,即如下所示:

XML 复制代码
 <TextBox
        Name="password"
        Width="500"
        Height="66"
        MaxLength="10"
        Text="{x:Bind VM.Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

若使用x:Bind不设置Mode=TwoWay,则会报下述错误:

Invalid binding assignment : 'UpdateSourceTrigger' may only be used with binding 'Mode=TwoWay'

若使用x:Bind不设置UpdateSourceTrigger=PropertyChanged,则会导致属性更新时不会及时通知VM,也就不会马上进行数据验证。

使用Bing暂未发现上述问题。

参考连接

https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.inotifydataerrorinfo?view=net-8.0

ObservableValidator Class (CommunityToolkit.Mvvm.ComponentModel) | Microsoft Learn

System.ComponentModel.DataAnnotations 命名空间 | Microsoft Learn

相关推荐
c#上位机7 分钟前
halcon多个区域合并为1个区域—union1
c#·上位机·halcon·机器视觉
c#上位机25 分钟前
halcon图像增强——图像取反
图像处理·算法·c#·halcon
zwm26988881536 分钟前
悦龙台 监控掉线问题
c#
kkkkkkkkl2441 分钟前
Prometheus指标入门详解
linux·服务器
c#上位机41 分钟前
halcon图像去噪—导向滤波
图像处理·人工智能·计算机视觉·c#·halcon
意疏42 分钟前
不用云服务器也能跨设备转写!CapsWriter+cpolar 实现离线语音协作自由
运维·服务器
小李独爱秋1 小时前
计算机网络经典问题透视:TCP的“误判”——非拥塞因素导致的分组丢失
服务器·网络·tcp/ip·计算机网络·智能路由器·php
切糕师学AI1 小时前
Z.EntityFramework.Extensions.Core 如何批量删除数据?
c#
CHANG_THE_WORLD2 小时前
Python 中的循环结构详解
开发语言·python·c#
派阿喵搞电子3 小时前
配置srs的鉴权时遇到的问题
服务器·docker·容器·srs