.NET Maui styling with DataTrigger

Viewed 51

Overview: I have two properties:

  1. IsPast
  2. IsCurrentMonth

If it's past or not current month I want to display label in red.

The following code is a shrink version of default Maui application. If you run it you get red label (expected). After one click it stays red (expected) but following clicks switch the red color on and off. Is it a bug or I don't understand the way DataTrigger/Style/whatever works:

View model:

public class ViewModel : INotifyPropertyChanged
    {
        private bool _isPast;
        public bool IsPast
        {
            get => _isPast;
            set
            {
                _isPast = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsPast)));
            }
        }

        private bool _isCurrentMonth;
        public bool IsCurrentMonth
        {
            get => _isCurrentMonth;
            set
            {
                _isCurrentMonth = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsCurrentMonth)));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

Then 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:local="clr-namespace:BugMaui"
             x:Class="BugMaui.MainPage"
             x:DataType="local:ViewModel">

    <VerticalStackLayout>

        <HorizontalStackLayout>
            <Label Text="IsPast: " />
            <Label Text="{Binding IsPast}" />
        </HorizontalStackLayout>

        <HorizontalStackLayout>
            <Label Text="IsCurrentMonth: " />
            <Label Text="{Binding IsCurrentMonth}" />
        </HorizontalStackLayout>

        <Label
            Text="Hello, World!"
            FontSize="32"
            HorizontalOptions="Center">
            <Label.Style>
                <Style TargetType="Label">
                    <Style.Triggers>
                        <DataTrigger TargetType="Label" Binding="{Binding IsPast}" Value="True">
                            <Setter Property="Background" Value="Red" />
                        </DataTrigger>
                        <DataTrigger TargetType="Label" Binding="{Binding IsCurrentMonth}" Value="False">
                            <Setter Property="Background" Value="Red" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Label.Style>
        </Label>

        <Button
            Text="Click me"
            Clicked="OnCounterClicked"/>

    </VerticalStackLayout>

</ContentPage>

And the code behind:

public partial class MainPage : ContentPage
{
    ViewModel viewModel;

    public MainPage()
    {
        InitializeComponent();
        viewModel = new ViewModel { IsCurrentMonth = true, IsPast = true };
        BindingContext = viewModel;
    }

    private void OnCounterClicked(object sender, EventArgs e)
    {
        viewModel.IsPast = !viewModel.IsPast;
        viewModel.IsCurrentMonth = !viewModel.IsCurrentMonth;
    }
}
1 Answers

You can express your condition (IsPast is true && IsCurrentMonth is false) better with a MultiTrigger like this:

<Label
    Text="Hello, World!"
    FontSize="32"
    HorizontalOptions="Center">
    <Label.Style>
        <Style TargetType="Label">
            <Style.Triggers>                                
                <MultiTrigger TargetType="Label">
                    <MultiTrigger.Conditions>
                        <BindingCondition Binding="{Binding IsPast}" Value="True" />
                        <BindingCondition Binding="{Binding IsCurrentMonth}" Value="False" />
                    </MultiTrigger.Conditions>
                    <Setter Property="Background" Value="Red" />
                </MultiTrigger>
            </Style.Triggers>
        </Style>
    </Label.Style>
</Label>

Check the .NET MAUI MultiTrigger documentation for more info.

Related