Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Displaying validation errors in .net MAUI

I'm using the .net Community Toolkit and MVVM to create simple page with a few form fields. I would like to display validation errors next to each field - e.g. using a Label control that has its visibility set to true if there is an error with the respective field, and the value set to the error message from the ViewModel.

At present, I can see that the HasErrors property is set to true if there's a problem with one of the fields, however I cannot see how to correctly 'pass' the validation errors to the UI, and make the label visible (hence I've left the IsVisible and Text properties empty below).

The key bits of my code setup are:

public partial class MyViewModel : ObservableValidator
{
    [ObservableProperty]
    [NotifyDataErrorInfo]
    [MinLength(3, ErrorMessage = "Flight number is required.")]
    [Required(ErrorMessage = "Flight number is required.")]
    private string flightNumber;

    [ObservableProperty]
    [NotifyDataErrorInfo]
    [Required(ErrorMessage = "Airline is required.")]
    private string airline;


    [ObservableProperty]
    [NotifyDataErrorInfo]
    [Required(ErrorMessage = "Destination is required.")]
    private string destination;


    [RelayCommand]
    private void Submit()
    {
        ValidateAllProperties();

        if (!HasErrors)
        {
            // Allow user to progress
        }
    }

    
}

And the XAML is:

<?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"
             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>

   </ContentPage.Resources>

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

          <!-- Flight Number Entry -->
          <Entry
                 Placeholder="Flight Number"
                 Text="{Binding FlightNumber}"
                 PlaceholderColor="Gray"/>

          <!-- Airline Entry -->
          <Entry Placeholder="Airline"
                 Text="{Binding Airline}"
                 PlaceholderColor="Gray"/>
          <Label Text=""
                 TextColor="Red"
                 IsVisible=""/>

          <!-- Destination Entry -->
          <Entry Placeholder="Destination"
                 Text="{Binding Destination}"
                 PlaceholderColor="Gray"/>
          <Label Text=""
                 TextColor="Red"
                 IsVisible=""/>

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

</ContentPage>
like image 502
MarkC80 Avatar asked Mar 05 '26 13:03

MarkC80


1 Answers

Here's an approach that I found got me 95% of the way toward what I wanted:

            <Entry
                Grid.Row="1"
                Grid.Column="0"
                x:Name="FlightOrigin"
                Text="{Binding DepartureAirport }"
                SemanticProperties.HeadingLevel="Level2"
                FontSize="Medium"
                HorizontalOptions="FillAndExpand"
                HorizontalTextAlignment="Start"
                MaxLength="3"
                TextTransform="Uppercase"
                Placeholder="e.g. LHR"
                IsSpellCheckEnabled="False"
                IsTextPredictionEnabled="False"
                VerticalOptions="Start">
                <Entry.Behaviors>
                    <toolkit:TextValidationBehavior
                        x:Name="DepartureAirportValidator"
                        InvalidStyle="{StaticResource InvalidEntryStyle}"
                        Flags="ValidateOnValueChanged"
                        MaximumLength="3"/>
                </Entry.Behaviors>
            </Entry>
            <Label Grid.Row="2"
                   Grid.Column="0"
                   x:Name="DepartureAirportInvalid"
                   Text="Please choose a valid airport."
                   TextColor="Red"
                   FontSize="Small">
                <Label.Triggers>
                    <DataTrigger TargetType="Label"
                                 Binding="{Binding Source={x:Reference DepartureAirportValidator},
                                       Path=IsNotValid}"
                                 Value="True">
                        <Setter Property="IsVisible"
                                Value="True"/>
                    </DataTrigger>

                </Label.Triggers>
            </Label>
like image 54
MarkC80 Avatar answered Mar 07 '26 01:03

MarkC80



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!