Home > Back-end >  How to make button highlight when hovered over using a template
How to make button highlight when hovered over using a template

Time:08-24

Recently started WPF and am very new to XAML. I'm trying to make a calculator that looks similar to the IOS one. However, after I changed the Button to Ellipse, the highlighting when hovered over or clicking on stopped working, if also the highlighting issue were to be fixed, how would I go about changing the colour of it?

<Button x:Name="ButtonEquals" Grid.Column="4" Grid.Row="6" Width="47" Height="47"
        Content="=" Foreground="White"
        BorderBrush="{x:Null}" Background="#FFFF9500">
    <Button.Template>
        <ControlTemplate TargetType="Button">
            <Grid>
                <Ellipse Fill="#FFFF9500"/>
                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
            </Grid>
        </ControlTemplate>
    </Button.Template>
</Button>

CodePudding user response:

You need to create Style of button instead Template. Button's template you can set inside style (read more about Style in WPF):

        <Button x:Name="ButtonEquals"
                Grid.Column="4"
                Grid.Row="6"
                Width="47"
                Height="47"
                Content="=">
            <Button.Style>
                <Style TargetType="Button">
                    <!-- Here is properties for buttons with same style-->
                    <Setter Property="Foreground" Value="White"/>
                    <Setter Property="BorderBrush" Value="{x:Null}"/>
                    <Setter Property="Background" Value="#FFFF9500"/>
                    
                    <!-- Here is your template -->
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="Button">
                                <Grid>
                                    <Ellipse Fill="{TemplateBinding Background}"/>
                                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                    
                    <!-- Here is style triggers for interact with button -->
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <!-- Set color as you wish -->
                            <Setter Property="Background" Value="LightSalmon"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
        </Button>

But actually, you need to create global ResourceDictionary (read about it) and there set styles for all buttons like <Style x:Key="CalculatorButton"> for set to buttons like <Button Content="1" Style="{StaticResource CalculatorButton}"/>

CodePudding user response:

You can add a Trigger to the ControlTemplate and target the Ellipse by name assigning an x:Name and referring to it via TargetName. This way, you can define other states as well.

<ControlTemplate TargetType="Button">
   <Grid>
      <Ellipse x:Name="MyEllipse" Fill="#FFFF9500"/>
      <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
   </Grid>
   <ControlTemplate.Triggers>
      <Trigger Property="IsDefaulted" Value="True">
         <Setter TargetName="MyEllipse" Property="Fill" Value="OrangeRed"/>
      </Trigger>
      <Trigger Property="IsMouseOver" Value="True">
         <Setter TargetName="MyEllipse" Property="Fill" Value="Blue"/>
      </Trigger>
      <Trigger Property="IsPressed" Value="True">
         <Setter TargetName="MyEllipse" Property="Fill" Value="Red"/>
      </Trigger>
      <Trigger Property="IsEnabled" Value="False">
         <Setter TargetName="MyEllipse" Property="Fill" Value="Gray"/>
      </Trigger>
   </ControlTemplate.Triggers>
</ControlTemplate>

This targets only the Fill of the Ellipse, without changing other controls in the template. However, the values are hardcoded and not changable from outside.

If you want the template to be customizable to a certain degree, then you can put it in a Style and bind properties on the templated control using TemplateBinding or a RelativeSource with TemplatedParent for two-way and special scenarios. Additionally, you can add a FocusVisualStyle that allows to specify a template for keyboard focusing.

<Style TargetType="Button">
   <Setter Property="Background" Value="#FFFF9500"/>
   <Setter Property="Foreground" Value="White"/>
   <Setter Property="FocusVisualStyle">
      <Setter.Value>
         <Style>
            <Setter Property="Control.Template">
               <Setter.Value>
                  <ControlTemplate>
                     <Ellipse StrokeDashArray="1 2" Stroke="DarkGreen" StrokeThickness="2"/>
                  </ControlTemplate>
               </Setter.Value>
            </Setter>
         </Style>
      </Setter.Value>
   </Setter>
   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="Button">
            <Grid>
               <Ellipse x:Name="MyEllipse" Fill="{TemplateBinding Background}"/>
               <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
            </Grid>
            <ControlTemplate.Triggers>
               <Trigger Property="IsDefaulted" Value="True">
                  <Setter TargetName="MyEllipse" Property="Fill" Value="OrangeRed"/>
               </Trigger>
               <Trigger Property="IsMouseOver" Value="True">
                  <Setter TargetName="MyEllipse" Property="Fill" Value="Blue"/>
               </Trigger>
               <Trigger Property="IsPressed" Value="True">
                  <Setter TargetName="MyEllipse" Property="Fill" Value="Red"/>
               </Trigger>
               <Trigger Property="IsEnabled" Value="False">
                  <Setter TargetName="MyEllipse" Property="Fill" Value="Gray"/>
               </Trigger>
            </ControlTemplate.Triggers>
         </ControlTemplate>
      </Setter.Value>
   </Setter>
</Style>

If you want to reuse the style on multiple buttons, add it to a resource dictionary in scope and assign an x:Key to refer to it via StaticResource or DynamicResource.

  • Related