Search code examples
c#.netmaui

How to conditionally use the 'default' color in MAUI?


I'm looking for a way to get the default color in MAUI so that I can respect system themes/etc. I have a field that I want to change color under certain conditions, but remain the "default" color, platform-independent, if not. I'm currently using the .NET MAUI MVVM Toolkit, so I have a converter defined as follows:

    <ContentPage.Resources>
        <x:Double x:Key="Threshold">0</x:Double>
        <Color x:Key="FalseColor">DarkRed</Color>
        <!--What goes in here?-->
        <Color x:Key="TrueColor"></Color>
        <toolkit:CompareConverter x:Key="isAboveThresholdConverter" 
                ComparisonOperator="Greater"
                ComparingValue="{StaticResource Key=Threshold}"
                TrueObject="{StaticResource TrueColor}"
                FalseObject="{StaticResource FalseColor}"/>
    </ContentPage.Resources>

which is used here:

    <Label Text="{Binding RunningTotal}" TextColor="{Binding RunningTotal, Converter={StaticResource isAboveThresholdConverter}}"  Grid.Row="2" Grid.Column="2"/>

How do I get this to be DarkRed if the condition is false, but set the text color to whatever the system default color for text is if true?

I have tried:

  • Leaving the TrueColor empty, as show in the example above
  • Writing null for TrueColor in XAML
  • Writing Default for TrueColor in XAML
  • Searching MAUI docs for a Color.Default field (I am unsure such a field exists, though apparently it did in WinUI3, and there's some workaround work that was done but I do not understand the specific commit history)

I would like to avoid:

  • Hardcoding Black and White as colors in the theme, since I'm only reasonably sure that those are the correct colors for text in the respective light/dark modes across all platforms and I want to do as little custom color work as possible.
  • Coding an individual color per platform (see How can I use Windows/Android accent color in .NET Maui? for an example of how to get the accent color for specifically Windows, with an Android solution in the commments)

Is there a way to respect system default color regardless of platform, or am I out of luck?


Solution

  • To get a default color, I suppose you can put a default label in the resource dictionary, e.g.

    <Label x:Key="DefaultLabel"/>
    

    Then you can refer to its color via {Binding TextColor, Source={StaticResource DefaultLabel}}

    Also, you can use MultiMathExpressionConverter in a DataTrigger as follows:

    <!-- Pseudo code - may contain syntax errors, default TrueColor is inferred -->
    <Label Text="{Binding RunningTotal}" >
        <Label.Triggers>
             <DataTrigger TargetType="Label"
                          Binding="{MultiBinding {Binding RunningTotal},
                                                 {Binding Source={StaticResource Threshold}},
                                                 Converter={StaticResource MultiMathExpressionConverter},
                                                 ConverterParameter='sign(x - x1)'}"
                          Value="-1">
                 <Setter Property="TextColor" Value="{StaticResource FalseColor}" />
             </DataTrigger>
        </Label.Triggers>
    </Label>
    
    I have a `MultiMathExpressionConverter` enhancement to support boolean and comparison operators. It would help me a lot if you vote on the issue and the corresponding PR:

    You can also solve this problem using boolean operators with the MultiMathExpressionConverter. Note these operators may need to use XAML friendly equivalents:

    Operator XAML XAML friendly
    && &amp;&amp; and
    || || or
    >= &gt;= ge
    > &gt; gt
    <= &lt;= le
    < &lt; lt
    <Label Text="{Binding RunningTotal}"
           TextColor="{MultiBinding {Binding RunningTotal},
                                    {Binding Source={StaticResource Threshold}},
                                    {Binding TextColor, Source={StaticResource DefaultLabel}},
                                    {Binding Source={StaticResource FalseColor}},
                                    Converter={StaticResource MultiMathExpressionConverter},
                                    ConverterParameter='x gt x1 ? x2 : x3'}" />