0

我想在 WPF 中以编程方式创建按钮,该按钮在 何时增长到特定大小IsMouseOver == true,并在 何时缩小到其原始大小IsMouseOver == false

为了实现这种行为,我派生了Button该类,并添加了一个DependencyProperty

public class ScalableButton : Button
{
    public Storyboard MouseOutAnimation
    {
        get { return (Storyboard)GetValue(MouseOutAnimationProperty); }
        set { SetValue(MouseOutAnimationProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MouseOutAnimation.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MouseOutAnimationProperty =
        DependencyProperty.Register("MouseOutAnimation", typeof(Storyboard), typeof(ScalableButton), new UIPropertyMetadata(null));

    public ScalableButton(double originalScale, Style style)
        : base()
    {
        CreateMouseOutAnimation(originalScale);
        RenderTransform = new ScaleTransform(originalScale, 1, 0.5, 0.5);
        RenderTransformOrigin = new Point(0.5, 0.5);
        Style = style;
        ApplyTemplate();
    }

    private void CreateMouseOutAnimation(double originalScale)
    {
        DoubleAnimation animX = new DoubleAnimation();
        animX.To = originalScale;
        animX.Duration = TimeSpan.FromMilliseconds(200);
        DoubleAnimation animY = new DoubleAnimation();
        animY.To = 1;
        animY.Duration = TimeSpan.FromMilliseconds(200);
        Storyboard sb = new Storyboard();
        sb.Children.Add(animX);
        sb.Children.Add(animY);
        Storyboard.SetTarget(sb, this.RenderTransform);
        Storyboard.SetTargetProperty(animX, new PropertyPath(ScaleTransform.ScaleXProperty));
        Storyboard.SetTargetProperty(animY, new PropertyPath(ScaleTransform.ScaleYProperty));
        MouseOutAnimation = sb;
    }
}

然后,我创建了一个Style用 aControlTemplate为我的按钮制作自定义外观,并添加了一个Storyboard资源来放大它们,另一个来缩小它们,这就是问题所在:

<Style TargetType="{x:Type rgw:ScalableButton}" x:Key="EllipseWithText" >
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type rgw:ScalableButton}">
                <ControlTemplate.Resources>
                    <Storyboard x:Key="MouseOverAnimation">
                        <DoubleAnimation Storyboard.TargetName="ButtonGrid" Storyboard.TargetProperty="RenderTransform.ScaleX" To="1.2" Duration="0:0:1" />
                        <DoubleAnimation Storyboard.TargetName="ButtonGrid" Storyboard.TargetProperty="RenderTransform.ScaleY" To="1.2" Duration="0:0:1" />
                    </Storyboard>
                    <Storyboard x:Key="MouseOutAnimation">
                        <!-- This would be the one which scales down -->
                    </Storyboard>
                </ControlTemplate.Resources>
                <Grid x:Name="ButtonGrid" RenderTransform="{TemplateBinding RenderTransform}" RenderTransformOrigin="0.5, 0.5">
                    <Ellipse x:Name="ButtonEllipse" Height="50" Width="150" Fill="#00000000" StrokeThickness="1" Stroke="Black" />
                    <TextBlock x:Name="ButtonText" Width="150" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Trigger.EnterActions>
                            <BeginStoryboard Storyboard="{StaticResource MouseOverAnimation}" />
                        </Trigger.EnterActions>
                        <Trigger.ExitActions>
                            <BeginStoryboard Storyboard="{StaticResource MouseOutAnimation}" />
                        </Trigger.ExitActions>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

那么,如何将 指定ScalableButton.MouseOutAnimation为资源?

或者有没有其他方法可以实现可扩展按钮?

4

1 回答 1

1

不需要派生按钮。

不要To在 ExitActions 动画中设置属性。这将自动从当前属性值动画回原始属性值。请注意,在下面的示例中,我最初设置了ScaleX = 0.5.

<Style TargetType="Button">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid RenderTransformOrigin="0.5, 0.5">
                    <Grid.RenderTransform>
                        <ScaleTransform x:Name="scale" ScaleX="0.5"/>
                    </Grid.RenderTransform>
                    <Ellipse Height="50" Width="150" Fill="Transparent" StrokeThickness="1" Stroke="Black" />
                    <TextBlock Width="150" HorizontalAlignment="Center" VerticalAlignment="Center"
                               TextAlignment="Center" TextWrapping="Wrap" Text="{TemplateBinding Content}"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Trigger.EnterActions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation
                                        Storyboard.TargetName="scale"
                                        Storyboard.TargetProperty="ScaleX"
                                        To="1.2" Duration="0:0:0.3"/>
                                    <DoubleAnimation Storyboard.TargetName="scale"
                                        Storyboard.TargetProperty="ScaleY"
                                        To="1.2" Duration="0:0:0.3"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.EnterActions>
                        <Trigger.ExitActions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation
                                        Storyboard.TargetName="scale"
                                        Storyboard.TargetProperty="ScaleX"
                                        Duration="0:0:0.2"/>
                                    <DoubleAnimation
                                        Storyboard.TargetName="scale"
                                        Storyboard.TargetProperty="ScaleY"
                                        Duration="0:0:0.2"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.ExitActions>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

编辑:虽然MinWidth肯定不是比例因子:你可以像下面这样绑定。

<ScaleTransform ScaleX="{Binding MinWidth,
    RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
于 2012-05-10T15:57:24.840 回答