Skip to content
This repository was archived by the owner on Jul 11, 2025. It is now read-only.
This repository was archived by the owner on Jul 11, 2025. It is now read-only.

Styling doesn't apply based on ControlState #263

@giulianob

Description

@giulianob

Styles with ControlState don't seem to actually apply. For example:

public class AppStyle : Style
{
    public AppStyle()
    {
        Button = new ButtonStyle
        {
            BackgroundColor = new StyleAwareValue<ControlState, Color>
            {
                [ControlState.Disabled] = Color.Grey,
                [ControlState.Default] = Color.Green,
                [ControlState.Hovered] = Colors.Red,
                [ControlState.Pressed] = Color.Black,
            }
        };
    }
}

// Then using it:
View body() =>
    new VStack
    {
         new Button("Enabled"),
         new Button("Disabled")
	    .Enabled(false),
     }.ApplyStyle(new AppStyle());

The second button should be grey. The first button should be red/black when hovered/pressed. The source generators are just getting the default value and doesn't seem like they apply the control state:

// Button.g.cs
Microsoft.Maui.Graphics.Color Microsoft.Maui.ITextStyle.TextColor => this.GetEnvironment<Microsoft.Maui.Graphics.Color>("Color") ?? default;

I can look at helping PR a change to implement this but would need some guidance on how to implement it. What I am thinking:

  1. CometGenerator attribute needs a list of states supported by each control. I believe by default every control supports at least Disabled, Default, and Hovered states but ITextButton needs to specify it also supports Pressed.
  2. ITextButton would need to generate a bool IsPressed which is updated based on Pressed/Released actions. Not sure how to best model this in the CometGenerateAttribute. Is this a one off case? Is it better to omit Pressed/Released from being generated and create a Button.cs with this logic?
  3. Source generator would emit a switch statement to fetch the correct value based on state. This could be done in a VisualState property. For example, if the ITextButton has states [ Pressed ] (default/hovered/disabled don't need to be specified) then the following switch would be created:
Microsoft.Maui.Graphics.Color Microsoft.Maui.ITextStyle.TextColor => this.GetEnvironment<Microsoft.Maui.Graphics.Color>("Color", VisualState) ?? default;

ControlState VisualState {
   get {
// not sure if order matters here
       if (IsPressed)
       {
          return ControlState.IsPressed;
       }
       if (IsFocused)
       {
          return ControlState.Hovered;
       }
       if (IsEnabled)
       {
         return ControlState.Default;
       }
       return ControlState.Disabled;
   }
}

Another option would be to add the switch inside of the GetEnvironment call. This would support the IsFocused/IsEnabled states but not sure how that would support IsPressed

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions