MAUI新生2.5-数据绑定和MVVM:MVVM的属性验证

一、MVVM的属性验证案例

Toolkit.Mvvm框架中的ObservableValidator类,提供了属性验证功能,可以使用我们熟悉的验证特性对属性的值进行验证,并将错误属性提取和反馈给UI层。以下案例实现对UI层的姓名和年龄两个输入框,进行表单提交验证。实现效果如下所示:

 

 

 

 

1、View 

<ContentPage ......>

    <ContentPage.BindingContext>
        <vm:MainPageViewModel />
    </ContentPage.BindingContext>

    <ScrollView>
        <VerticalStackLayout>

            <!--姓名输入框及其验证信息-->
            <Entry Text="{Binding Name}" Placeholder="请输入姓名" />
            <Label Text="{Binding NameErrorMsg}" TextColor="Red" />

            <!--年龄输入框及其验证信息-->
            <Entry Text="{Binding Age}" Placeholder="请输入年龄" />
            <Label Text="{Binding AgeErrorMsg}" TextColor="Red" />

            <!--汇总验证信息-->
            <Label Text="{Binding AllErrorMsg}" TextColor="Red" />

            <!--提交按钮验证表单字段-->
            <Button Command="{Binding SubmitNameCommand}" Text="单独验证姓名字段" />
            <Button Command="{Binding SubmitAgeCommand}" Text="单独验证年龄字段" />
            <Button Command="{Binding SubmitAllCommand}" Text="验证所有字段" />

        </VerticalStackLayout>
    </ScrollView>
</ContentPage>

 

 

2、ViewModel

public partial class MainPageViewModel:ObservableValidator
{
    /* ========定义Name和Age属性 */
    [ObservableProperty]
    [Required(ErrorMessage = "姓名必填!")] //框架内置的验证特性
    [MinLength(2,ErrorMessage = "最少2个字符")] //框架内置的验证特性
    [MaxLength(10,ErrorMessage = "最多10个字符")] //框架内置的验证特性
    private string name;

    [ObservableProperty]
    [CustomValidation(typeof(MainPageViewModel),nameof(ValidateAge1))] //使用通过静态方法定义的自定义验证特性
    [ValidateAge2(1,17)] //使用通过验证类的自定义验证特性
    private int age;


    /* ========定义姓名、年龄以及所有字段的报错信息,通过Binding反馈给UI层 */
    [ObservableProperty]
    private string nameErrorMsg; //姓名验证报错信息  
    [ObservableProperty]
    private string ageErrorMsg; //年龄验证报错信息    
    [ObservableProperty]
    private string allErrorMsg; //所有属性验证报错信息


    /* ========以下命令使用ObservableValidator对象提供的方法或属性,对Name属性进行检验
     * 方法ValidateProperty(属性值,"属性名"),对特定属性执行校验
     * 属性HasErrors,判断是否有检验错误
     * 方法GetErrors("属性名"),获得ValidationResult对象,此对象的ErrorMessage属性为错误信息 */
    [RelayCommand]
    private void SubmitName()
    {
        ValidateProperty(Name,"Name");
        if (HasErrors)
        {
            NameErrorMsg = string.Join(Environment.NewLine, GetErrors("Name").Select(e => e.ErrorMessage));
        }
        else
        {
            NameErrorMsg = string.Empty;
        }
    }

    //========同上
    [RelayCommand]
    private void SubmitAge()
    {
        //验证Age属性,
        ValidateProperty(Age,"Age");
        if (HasErrors)
        {
            AgeErrorMsg = string.Join(Environment.NewLine, GetErrors("Age").Select(e => e.ErrorMessage));
        }
        else
        {
            AgeErrorMsg = string.Empty;
        }
    }

    /* ========以下命令校验所有属性
     * 方法ValidateAllProperties(),会检验所有属性
     * 属性HasErrors,判断是否有检验错误
     * 方法GetErrors(),获得所有ValidationResult对象,此对象的ErrorMessage属性,获取所有校验错误 */
    [RelayCommand]
    private void SubmitAll()
    {
        ValidateAllProperties();
        if (HasErrors)
        {
            AllErrorMsg = string.Join(Environment.NewLine, GetErrors().Select(e => e.ErrorMessage));
        }
        else
        {
            AllErrorMsg = string.Empty;
        }
    }

    /* ========自定义验证特性方法①:静态方法
     * 返回值为ValidationResult,如果验证成功,返回ValidateResult.Success,如果失败,则返回new("报错信息")
     * 第一个参数为待验证的属性,第二个参数为参证上下文ValidationContext,可以获得当前实例、成员等信息
     * 如通过以下代码【(MainPageViewModel)context.ObjectInstance】获得当前对象 */
    public static ValidationResult ValidateAge1(int age, ValidationContext context)
    {
        if (age >= 18 && age <= 100)
        {
            return ValidationResult.Success;
        }
        return new("年龄最小18岁最大100岁");
        
    }
}

/* ========自定义验证特性方式②:
 * 定义继承自ValidationAttribute的验证类。推荐方式,可以重用。
 * 定义两个属性MaxAge和MinAge,使用特性时,通过特性参数赋值
 * 必须重写IsValid方法,如果验证成功,返回ValidationResult.Success。如果失败,则返回new("错误信息") */
public sealed class ValidateAge2Attribute : ValidationAttribute
{
    //属性MaxAge和MinAge,将通过特性参数赋值
    public int MaxAge { get; }
    public int MinAge { get; }
    public ValidateAge2Attribute(int maxAge, int minAge)
    {
        MaxAge = maxAge;
        MinAge = minAge;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        int age = (int)value;
        if (age >= MinAge && age <= MaxAge)
        {
            return ValidationResult.Success;
        }
        return new($"年龄最小{MinAge},最大{MaxAge}");
    }
}

 

3、基本实现说明:

  • UI层的表单字段、错误信息字段,与ViewModel的属性绑定。
  • ViewModel派生自ObservableValidator(ObservableValidator派生自ObservableObject,也具有绑定功能)。
  • 待验证属性,使用验证特性标注。验证特性既可以使用框架内置的特性(推荐),也可以自定义验证特性。自定义验证特性的方式有两种:静态验证方法和验证类特性。
  • UI层绑定命令,在命令中执行属性值检验,并提取校验错误信息赋值给错误信息字段。
  • ObservableValidator提供的几个方法和属性:ValidateProperty方法-校验指定属性、ValidateAllProperties方法-校验所有属性、HasErrors属性-判断是否有校验错误、GetErrors方法-获取指定属性或所有属性的校验错误信息。

 

 

二、常用的验证特性:可直接查看文档

 

posted @ 2023-02-04 23:30  functionMC  阅读(818)  评论(0编辑  收藏  举报