Home > Enterprise >  Customizing a WPF button control style with geometry path
Customizing a WPF button control style with geometry path

Time:10-07

I am having difficulties to wrap my head around using Shapes.Path geometry data as content for a button. The style concept is: content inflates when the mouse enters and deflates when leaving. This works all as intended except for customization. I seem to be unable to change the path data when using this style.


        <PathGeometry x:Key="PauseGeo">
                M13,16V8H15V16H13M9,16V8H11V16H9M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4Z
        </PathGeometry>

        <PathGeometry x:Key="PlayGeo">
                M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M10,16.5L16,12L10,7.5V16.5Z
        </PathGeometry>


        <Style x:Key="ButtonInflateStyle" TargetType="{x:Type Button}">
            <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Padding" Value="1"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="true">
                            <Grid x:Name="ButtonGrid" RenderTransformOrigin="0.5,0.5" >
                                <Grid.RenderTransform>
                                    <ScaleTransform/>
                                </Grid.RenderTransform>
                                <Path x:Name="PathButton" Data="{StaticResource PlayGeo}" Fill="White" Stretch="Uniform"/>
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <EventTrigger RoutedEvent="MouseEnter">
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation
                                            Storyboard.TargetName="ButtonGrid"
                                            Storyboard.TargetProperty="(Grid.RenderTransform).(ScaleTransform.ScaleX)"
                                            From="1"
                                            To="1.1"
                                            Duration="0:0:0.3" />
                                        <DoubleAnimation
                                            Storyboard.TargetName="ButtonGrid"
                                            Storyboard.TargetProperty="(Grid.RenderTransform).(ScaleTransform.ScaleY)"
                                            From="1"
                                            To="1.1"
                                            Duration="0:0:0.3" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </EventTrigger>
                            <EventTrigger RoutedEvent="MouseLeave">
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation
                                            Storyboard.TargetName="ButtonGrid"
                                            Storyboard.TargetProperty="(Grid.RenderTransform).(ScaleTransform.ScaleX)"
                                            From="1.1"
                                            To="1"
                                            Duration="0:0:0.3" />
                                        <DoubleAnimation
                                            Storyboard.TargetName="ButtonGrid"
                                            Storyboard.TargetProperty="(Grid.RenderTransform).(ScaleTransform.ScaleY)"
                                            From="1.1"
                                            To="1"
                                            Duration="0:0:0.3" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </EventTrigger>
                            <EventTrigger RoutedEvent="Click">
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetProperty="(Grid.Opacity)" From="1" To="0" BeginTime="0:0:0" Duration="0:0:.125" AutoReverse="True"/>
                                    </Storyboard>
                                </BeginStoryboard>
                            </EventTrigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Fill" TargetName="PathButton" Value="Gray"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

And use it like this

<Button Style="{StaticResource ButtonInflateStyle}" x:Name="buttonPausePlay" Grid.Column="2">
    <Path Data="{StaticResource PauseGeo}"></Path>
</Button>
            

Button image remains the on as defined in style.

I prefer XAML only solutions but I assume a CustomControl is needed. Or is it? Could someone point me in the right direction, please?

CodePudding user response:

The Path in the ControlTemplate could use the Button's Content for its Data:

<Path x:Name="PathButton"
      Data="{TemplateBinding Content}"
      Fill="White" Stretch="Uniform"/>

Then you would assign a Geometry to the Button's Content when you use it:

<Button Style="{StaticResource ButtonInflateStyle}"
        Content="{StaticResource PauseGeo}" .../>

or

<Button Style="{StaticResource ButtonInflateStyle}">
    <StaticResource ResourceKey="PauseGeo"/>
</Button>
  • Related