Xamarin.forms: [Bug] UWP Button BackgroundColor turns gray when hovering

Created on 8 Jan 2020  路  5Comments  路  Source: xamarin/Xamarin.Forms

Description

UWP Button BackgroundColor turns gray when hovering on it while targeting builds: 17763 and 18362, problem doesn't appear in creators update (16299)

Steps to Reproduce

  1. Create a XF button with background color
  2. target UWP 17763 or 18362
  3. hover on the button

Expected Behavior

Button preserves its background color (similar to what we get when targeting version 16299)

Actual Behavior

Button turns to gray (or whatever default theme)

Basic Information

  • UWP: SDK versions: 17763 and 18362

Workaround

In UWP App.Xaml Resources:

<Style x:Key="ButtonStyle" TargetType="Button">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Grid x:Name="RootGrid"
                                  Background="{TemplateBinding Background}">
                                <VisualStateManager.VisualStateGroups>
                                    <VisualStateGroup x:Name="CommonStates">
                                        <VisualState x:Name="Normal">
                                            <Storyboard>
                                                <PointerUpThemeAnimation Storyboard.TargetName="RootGrid" />
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="PointerOver">
                                            <Storyboard>
                                                <PointerUpThemeAnimation Storyboard.TargetName="RootGrid" />
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="Pressed">
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid"
                                                                               Storyboard.TargetProperty="Background">
                                                    <DiscreteObjectKeyFrame KeyTime="0"
                                                                            Value="{ThemeResource SystemControlBackgroundBaseMediumLowBrush}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                                               Storyboard.TargetProperty="BorderBrush">
                                                    <DiscreteObjectKeyFrame KeyTime="0"
                                                                            Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                                               Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0"
                                                                            Value="{ThemeResource SystemControlHighlightBaseHighBrush}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <PointerDownThemeAnimation Storyboard.TargetName="RootGrid" />
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="Disabled">
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid"
                                                                               Storyboard.TargetProperty="Background">
                                                    <DiscreteObjectKeyFrame KeyTime="0"
                                                                            Value="{ThemeResource SystemControlBackgroundBaseLowBrush}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                                               Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0"
                                                                            Value="{ThemeResource SystemControlDisabledBaseLowBrush}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                                               Storyboard.TargetProperty="BorderBrush">
                                                    <DiscreteObjectKeyFrame KeyTime="0"
                                                                            Value="{ThemeResource SystemControlDisabledTransparentBrush}" />
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </VisualState>
                                    </VisualStateGroup>
                                </VisualStateManager.VisualStateGroups>
                                <ContentPresenter x:Name="ContentPresenter"
                                                  BorderBrush="{TemplateBinding BorderBrush}"
                                                  BorderThickness="{TemplateBinding BorderThickness}"
                                                  Content="{TemplateBinding Content}"
                                                  ContentTransitions="{TemplateBinding ContentTransitions}"
                                                  ContentTemplate="{TemplateBinding ContentTemplate}"
                                                  Padding="{TemplateBinding Padding}"
                                                  HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                                  VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                                  AutomationProperties.AccessibilityView="Raw" />
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

Then create UWP button renderer

 public class CustomButtonRenderer : ButtonRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {
                var style = Application.Current.Resources["ButtonStyle"] as Style;
                Control.Style = style;
            }
        }
}
3 in-progress high impact UWP bug

All 5 comments

Is this issue planned to be fixed?

We are having this issue too. We're trying to get get a Windows release out using shared code from our Android and iOS apps. Please help Xamarin! I'd be happy with a workaround.

@mnxamdev I updated the issue with my workaround, hope it works for you. don't forget to export your renderer

Beat me to it @MhAllan ! This was a real pain to figure out. I too had to create a custom control template too except all I did was add an empty PointerOver visual state. I'm unclear though if I need to add additional {TemplateBinding X} to respective properties to make sure all properties are bound on the consumed/declared button:

<ControlTemplate x:Key="DefaultButtonControlTemplate" TargetType="Button">
        <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="PointerOver"/>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
            <ContentPresenter 
                x:Name="ContentPresenter" 
                AutomationProperties.AccessibilityView="Raw" 
                BorderBrush="{TemplateBinding BorderBrush}" 
                BorderThickness="{TemplateBinding BorderThickness}"
                ContentTemplate="{TemplateBinding ContentTemplate}" 
                ContentTransitions="{TemplateBinding ContentTransitions}" 
                Content="{TemplateBinding Content}" 
                HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" 
                Padding="{TemplateBinding Padding}" 
                VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" 
                TextWrapping="WrapWholeWords"/>
        </Grid>
    </ControlTemplate>
    public class UWPButton : ButtonRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {
                Control button = Control;
                var template = Windows.UI.Xaml.Application.Current.Resources["DefaultButtonControlTemplate"] as ControlTemplate;
                button.Template = template;
            }
        }
    }

@MhAllan Thank you very much for your workaround. It works also for ImageButton.

Was this page helpful?
0 / 5 - 0 ratings