You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI中结合MVVM与Community Toolkit显示表单验证错误的方法

.NET Community Toolkit MVVM表单验证错误UI展示方案

问题描述

使用.NET Community Toolkit的MVVM框架创建表单页面,希望在每个输入字段旁用Label显示对应验证错误:当字段验证失败时,Label可见并显示ViewModel中定义的错误信息。目前已确认字段验证失败时HasErrors属性会变为true,但不清楚如何将具体错误信息传递到UI以设置Label的Text和IsVisible。

解决方案

核心原理

ObservableValidator实现了INotifyDataErrorInfo接口,通过GetErrors(string propertyName)方法可以获取指定属性的所有验证错误信息。我们可以直接在XAML中绑定这个方法的返回值,动态更新Label的内容和可见性。

修改后的XAML代码

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:viewmodel="clr-namespace:TestApp.ViewModels"
             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             xmlns:converters="clr-namespace:TestApp.Converters"
             xmlns:validation="clr-namespace:System.ComponentModel;assembly=System.ComponentModel.Annotations"
             x:Class="TestApp.Views.TestPage"
             Title="Test">
   <ContentPage.Resources>
          <Style x:Key="InvalidEntryStyle"
                 TargetType="Entry">
                 <Setter Property="TextColor"
                         Value="Red"/>
          </Style>
          <Style x:Key="ValidEntryStyle"
                 TargetType="Entry">
                 <Setter Property="TextColor"
                         Value="Green"/>
          </Style>
          <Style x:Key="ErrorLabelStyle" TargetType="Label">
              <Setter Property="TextColor" Value="Red"/>
              <Setter Property="FontSize" Value="Small"/>
          </Style>

          <converters:FirstErrorConverter x:Key="FirstErrorConverter"/>
          <converters:BoolToStyleConverter x:Key="BoolToStyleConverter"/>
   </ContentPage.Resources>

   <StackLayout Padding="20"
                Spacing="10">

          <!-- Flight Number Entry -->
          <Entry
                 Placeholder="Flight Number"
                 Text="{Binding FlightNumber}"
                 PlaceholderColor="Gray"
                 Style="{Binding (validation:INotifyDataErrorInfo.HasErrors)[FlightNumber], Converter={StaticResource BoolToStyleConverter}, ConverterParameter={x:Array Type={x:Type Style}, xmlns:x='http://schemas.microsoft.com/winfx/2009/xaml'}>{x:StaticResource ValidEntryStyle}{x:StaticResource InvalidEntryStyle}</x:Array>}"/>
          <Label Style="{StaticResource ErrorLabelStyle}"
                 Text="{Binding (validation:INotifyDataErrorInfo.GetErrors)['FlightNumber'], Converter={StaticResource FirstErrorConverter}}"
                 IsVisible="{Binding (validation:INotifyDataErrorInfo.HasErrors)[FlightNumber]}"/>

          <!-- Airline Entry -->
          <Entry Placeholder="Airline"
                 Text="{Binding Airline}"
                 PlaceholderColor="Gray"/>
          <Label Style="{StaticResource ErrorLabelStyle}"
                 Text="{Binding (validation:INotifyDataErrorInfo.GetErrors)['Airline'], Converter={StaticResource FirstErrorConverter}}"
                 IsVisible="{Binding (validation:INotifyDataErrorInfo.HasErrors)[Airline]}"/>

          <!-- Destination Entry -->
          <Entry Placeholder="Destination"
                 Text="{Binding Destination}"
                 PlaceholderColor="Gray"/>
          <Label Style="{StaticResource ErrorLabelStyle}"
                 Text="{Binding (validation:INotifyDataErrorInfo.GetErrors)['Destination'], Converter={StaticResource FirstErrorConverter}}"
                 IsVisible="{Binding (validation:INotifyDataErrorInfo.HasErrors)[Destination]}"/>

          <!-- Submit Button -->
          <Button Text="Submit"
                  Command="{Binding SubmitCommand}"/>
   </StackLayout>
</ContentPage>

补充必要的转换器

FirstErrorConverter.cs(提取第一条错误信息)

using System;
using System.Collections;
using System.Globalization;
using Microsoft.Maui.Controls;

namespace TestApp.Converters
{
    public class FirstErrorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is IEnumerable errors)
            {
                foreach (var error in errors)
                {
                    if (error is string errorMessage)
                    {
                        return errorMessage;
                    }
                }
            }
            return string.Empty;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

BoolToStyleConverter.cs(可选:根据错误状态切换Entry样式)

using System;
using System.Globalization;
using Microsoft.Maui.Controls;

namespace TestApp.Converters
{
    public class BoolToStyleConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is bool hasErrors && parameter is Style[] styles && styles.Length == 2)
            {
                return hasErrors ? styles[1] : styles[0];
            }
            return parameter is Style[] defaultStyles ? defaultStyles[0] : null;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

关键说明

  1. IsVisible绑定:通过(validation:INotifyDataErrorInfo.HasErrors)[PropertyName]直接绑定指定属性的错误状态,属性验证失败时自动设为true。
  2. Text绑定:通过(validation:INotifyDataErrorInfo.GetErrors)['PropertyName']获取该属性的错误集合,再用FirstErrorConverter取出第一条错误信息显示。
  3. ViewModel无需修改:你现有的ViewModel代码已正确使用ObservableValidator和NotifyDataErrorInfo特性,无需额外调整。

内容的提问来源于stack exchange,提问作者MarkC80

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 17:34:51