如何使用自定义控件模板以按钮样式执行边框画笔动画



我有一个按钮样式定义如下:

<LinearGradientBrush x:Key="Brush_NavButtonBorder0" StartPoint="0,0" EndPoint="0,1" >
    <GradientStop Color="#00383f47" Offset="0" />
    <GradientStop Color="#FF383f47" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="Brush_NavButtonBorder4" StartPoint="0,0" EndPoint="0,1" >
    <GradientStop Color="#FF414f5a" Offset="0" />
    <GradientStop Color="#11414f5a" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="Brush_NavButtonBackground" StartPoint="0,0" EndPoint="0,1" >
    <GradientStop Color="#FF3f505a" Offset="0" />
    <GradientStop Color="#FF37454e" Offset="0.75" />
    <GradientStop Color="#FF2f3c44" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="Brush_NavButtonPressedBackground" StartPoint="0,0" EndPoint="0,1" >
    <GradientStop Color="#FF3f505a" Offset="1" />
    <GradientStop Color="#FF37454e" Offset="0.25" />
    <GradientStop Color="#FF2f3c44" Offset="0" />
</LinearGradientBrush>
<Style x:Key="NavigationButton" TargetType="Button">
    <Setter Property="FocusVisualStyle" Value="{x:Null}" />
    <Setter Property="Foreground" Value="Gainsboro" />
    <Setter Property="FontSize" Value="14" />
    <Setter Property="Background" Value="{StaticResource Brush_NavButtonBackground}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}" x:Name="MainControlTemplate">
                <Grid>
                    <Border x:Name="outerBorder" CornerRadius="5" BorderThickness="1" BorderBrush="{StaticResource Brush_NavButtonBorder0}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True" />
                    <Border Margin="1" CornerRadius="4" BorderThickness="1" BorderBrush="{StaticResource Brush_NavButtonBorder4}" Background="Transparent" SnapsToDevicePixels="True">
                        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="content"/>
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <!--<Setter TargetName="outerBorder" Property="BorderBrush" Value="Gray" />-->
                        <Trigger.EnterActions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <ColorAnimation Storyboard.TargetName="outerBorder"
                                                    Storyboard.TargetProperty="(Border.BorderBrush).(GradientBrush.GradientStops)[0].(GradientStop.Color)"
                                                    To="Gray"
                                                    Duration="0:0:0.2" />
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.EnterActions>
                    </Trigger>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="Background" Value="{StaticResource Brush_NavButtonPressedBackground}" />
                        <Setter TargetName="content" Property="RenderTransform" >
                            <Setter.Value>
                                <TranslateTransform X="2.0" Y="2.0" />
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Opacity" Value="0.5" />
                    </Trigger>
                    <Trigger Property="IsKeyboardFocused" Value="True">
                        <Setter Property="FocusVisualStyle" Value="{StaticResource MyFocusVisualStyle}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

这种风格有几个问题:1.当我将鼠标悬停在按钮上时,使用此样式的所有其他按钮都会与动画做出反应,而不仅仅是我结束的按钮。2.我想对整个边框的颜色进行动画处理,而不仅仅是第0个渐变停止点,但是我似乎找不到一种方法来做到这一点。

ColorAnimation部分上方的注释行几乎完全符合我的需求,除了它在鼠标悬停时立即显示灰色的BorderBrush - 我希望它显示带有动画的灰色BorderBrush。

这似乎应该很简单,但我不知道该怎么做。有谁知道如何以正确的方式做到这一点?

它更改所有按钮边框的原因是您实际上是在更改渐变画笔中的颜色。 由于具有该样式的所有按钮实例共享相同的渐变画笔,因此所有画笔的边框都会更改。

有很多方法可以解决这个问题,但其中之一是使有问题的画笔成为样式本身的资源,因此它不会以相同的方式共享。 以下代码片段演示了您需要更改的所有内容(从顶级资源中删除Brush_NavButtonBorder0,并将其添加到按钮样式的资源中):

编辑:包括更新的完整样式

<Color x:Key="BorderColor">#00383f47</Color>
<!-- Other Brushes (NOT Brush_NavButtonBorder0) -->
<Style x:Key="NavigationButton" TargetType="Button">
  <Setter Property="FocusVisualStyle" Value="{x:Null}" />
  <Setter Property="Foreground" Value="Gainsboro" />
  <Setter Property="FontSize" Value="14" />
  <Setter Property="Background" Value="{StaticResource Brush_NavButtonBackground}" />
  <Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type Button}" x:Name="MainControlTemplate">
            <ControlTemplate.Resources>
                <LinearGradientBrush x:Key="Brush_NavButtonBorder0" StartPoint="0,0" EndPoint="0,1" >
                            <GradientStop Color="{StaticResource BorderColor}" Offset="0" />
                    <GradientStop Color="#FF383f47" Offset="1" />
                </LinearGradientBrush>
            </ControlTemplate.Resources>
            <Grid>
                <Border x:Name="outerBorder" CornerRadius="5" BorderThickness="1" BorderBrush="{StaticResource Brush_NavButtonBorder0}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True" />

                <Border Margin="1" CornerRadius="4" BorderThickness="1" BorderBrush="{StaticResource Brush_NavButtonBorder4}" Background="Transparent" SnapsToDevicePixels="True">
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="content"/>
                </Border>
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <!--<Setter TargetName="outerBorder" Property="BorderBrush" Value="Gray" />-->
                    <Trigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetName="outerBorder"
                                        Storyboard.TargetProperty="(Border.BorderBrush).(GradientBrush.GradientStops)[0].(GradientStop.Color)"
                                        To="Gray"
                                        Duration="0:0:0.2" />
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.EnterActions>
                    <Trigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetName="outerBorder"
                                        Storyboard.TargetProperty="(Border.BorderBrush).(GradientBrush.GradientStops)[0].(GradientStop.Color)"
                                        To="{StaticResource BorderColor}"
                                        Duration="0:0:0.2" />
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.ExitActions>
                </Trigger>
                <Trigger Property="IsPressed" Value="True">
                    <Setter Property="Background" Value="{StaticResource Brush_NavButtonPressedBackground}" />
                    <Setter TargetName="content" Property="RenderTransform" >
                        <Setter.Value>
                            <TranslateTransform X="2.0" Y="2.0" />
                        </Setter.Value>
                    </Setter>
                </Trigger>
                <Trigger Property="IsEnabled" Value="False">
                    <Setter Property="Opacity" Value="0.5" />
                </Trigger>
                <!--<Trigger Property="IsKeyboardFocused" Value="True">
                    <Setter Property="FocusVisualStyle" Value="{StaticResource MyFocusVisualStyle}" />
                </Trigger>-->
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Setter.Value>
</Setter>

这意味着每个按钮实例都会获得自己的 LinearGradientBrush 副本,并且鼠标悬停触发器动画仅影响鼠标悬停的按钮的动画。

同样,有许多不同的方法可以解决此问题,但上面的代码片段是我能想到的最简单的代码片段,考虑到您当前的代码。

最新更新