xamlinheritanceconditional-statementsbindingmaui

.NET Maui - option to neuter property binding


In .NET Maui I have this XAML:

        <Style x:Key="GreenLabelStyle" TargetType="Label">
            <Setter Property="TextColor" Value="Green"/>                      
        </Style>              

       <Label Style="{StaticResource GreenLabelStyle}" 
              Text="Some text"
              TextColor="{Binding SometimesOverrideColor}"
              />

       <CheckBox IsChecked="{Binding OverrideColorStyle}"/>

The Label's TextColor is bound to this property:

    public Color SometimesOverrideColor
    {
        get
        {
            return OverrideColorStyle ? Colors.Pink : Colors.Green; // works, but not DRY
        }
    }

Even though I have a specified a (bound) TextColor, I want the option to say "ignore this property setting and act as though there were no explicit TextColor on the Label". I tried returning null for SometimesOverrideColor, but that didn't work. I want to use the value of the Label's style (i.e. green).

Obviously, I can return Colors.Green in SometimesOverrideColor, but that repeats the value specified in the style. If I changed the style I would have to remember to update the property.

What I have in mind is like the inherit keyword in CSS. If I could return Color.Inherit that would be great!


Solution

  • Based on my understanding of your question I would do something to the effect of this

     <Style TargetType="Label">
            <Setter Property="TextColor" Value="Black" />
            <Setter Property="FontFamily" Value="OpenSansRegular" />
            <Setter Property="FontSize" Value="14" />
        </Style>
    
        <Style x:Key="SometimesOverrideColor" TargetType="Label">
            <Setter Property="TextColor" Value="Pink" />
        </Style>
    
        <Style x:Key="GreenLabelStyle" TargetType="Label">
            <Setter Property="TextColor" Value="Green" />
        </Style>
    

    And then write a short converter that would conditionally apply this:

    
    //Name this sensibly 
    public abstract class WhateverColorConveter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is not bool condition)
            {
                return null; // in case someone uses the converter but is a smartass
            }
    
            return  Application.Current.Resources.GetResource<Style>(condition ? "SometimesOverrideColor" : "GreenLabelStyle");
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    
    

    GetResource is an extension I have created:

     public static T GetResource<T>(this ResourceDictionary dictionary, string key)
        {
            if (dictionary.TryGetValue(key, out var value) && value is T resource)
                return resource;
            else
                return default;
        }
    

    And then this would be used with your XAML code style, don't forget to add this into your resources as a static resource:

    
    <ContentPage.Resources>
        <converters:WhateverColorConveter x:Key="WhateverColorConverter" />
    </ContentPage.Resources>
    
    

    And then use this :

    <Label Style={Binding Condition, Converter={StaticResource WhateverColorConverter}}/>