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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions