xaml - 如何在 Silverlight 5 中使用 VisualStateManager 重用 Storyboard

标签 xaml animation silverlight-5.0 resourcedictionary visualstatemanager

这个问题以前曾被问过,但在大多数情况下不超过 2 年前,并且通常特定于 WPF。答案可能仍然相同,但它就在这里。我正在尝试构建一个三角形(箭头)按钮,当鼠标悬停在其上方时,该按钮会改变颜色并增大大小。我已经为一个按钮工作了。但是现在我需要带有指向不同方向的箭头的按钮。我想尽可能多地重用代码。如果不使用自定义按钮控件,我想不出完全使用相同样式的方法,因此我试图通过将鼠标悬停动画作为资源来重用它。当我在按钮模板的 VisualStateManager 中将 Storyboard 引用为 StaticResource 时,它​​会使我的按钮完全消失。为什么这不起作用?

<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:System="clr-namespace:System;assembly=mscorlib" mc:Ignorable="d"
x:Class="SilverlightTest.MainPage"
Width="640" Height="480">
<UserControl.Resources>
    <Storyboard x:Key="ArrowMouseOver">
        <DoubleAnimation Duration="0:0:0.165" To="1.25" Storyboard.TargetProperty="(UiElement.RenderTransform).(ScaleTransform.ScaleX)" Storyboard.TargetName="polygon"/>
        <DoubleAnimation Duration="0:0:0.165" To="1.25" Storyboard.TargetProperty="(UiElement.RenderTransform).(ScaleTransform.ScaleY)" Storyboard.TargetName="polygon"/>
        <ColorAnimation Duration="0:0:0.165" To="#FF9BD6FF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/>
        <ColorAnimation Duration="0:0:0.165" To="#FF70ACDF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/>
        <ColorAnimation Duration="0:0:0.165" To="#FF7DAEFF" Storyboard.TargetProperty="(Shape.Stroke).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/>
        <ColorAnimation Duration="0:0:0.165" To="#FF2B5CB4" Storyboard.TargetProperty="(Shape.Stroke).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/>
    </Storyboard>

    <Style x:Key="LeftArrow" TargetType="Button">
        <Setter Property="Cursor" Value="Hand"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Grid x:Name="grdRoot" RenderTransformOrigin="0.5,0.5">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualStateGroup.Transitions>
                                    <VisualTransition From="MouseOver" GeneratedDuration="0:0:0.165"/>
                                </VisualStateGroup.Transitions>
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="MouseOver" Storyboard="{StaticResource ArrowMouseOver}">
                                </VisualState>
                                <VisualState x:Name="Pressed"/>
                                <VisualState x:Name="Disabled"/>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Polygon x:Name="polygon" Grid.Row="0" Margin="1" StrokeThickness="{TemplateBinding BorderThickness}" HorizontalAlignment="Center" RenderTransformOrigin="0.5,0.5">
                            <Polygon.Points>
                                <Point X="10"/>
                                <Point X="0" Y="5" />
                                <Point Y="10" X="10" />
                            </Polygon.Points>
                            <Polygon.RenderTransform>
                                <ScaleTransform />
                            </Polygon.RenderTransform>
                            <Polygon.Fill>
                                <LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1">
                                    <GradientStop Color="#FFA9A9A9"/>
                                    <GradientStop Color="#FFD3D3D3" Offset="1"/>
                                </LinearGradientBrush>
                            </Polygon.Fill>
                            <Polygon.Stroke>
                                <LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1">
                                    <GradientStop Color="#FF696969"/>
                                    <GradientStop Color="#FF939393" Offset="1"/>
                                </LinearGradientBrush>
                            </Polygon.Stroke>
                        </Polygon>
                        <ContentPresenter Grid.Row="1" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
    <Button Style="{StaticResource LeftArrow}" HorizontalAlignment="Left" VerticalAlignment="Top">
    </Button>
</Grid>

最佳答案

听起来您应该介绍自己的 Button类(class)。
我会这样做:

<my:GlowingArrowButton ArrowDirection="Left"/>

还有你的 generic.xaml:
<Style TargetType="my:GlowingArrowButton">
    <Setter Property="Cursor" Value="Hand"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="my:GlowingArrowButton">
                <Grid x:Name="grdRoot" RenderTransformOrigin="0.5,0.5">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualStateGroup.Transitions>
                                <VisualTransition From="MouseOver" GeneratedDuration="0:0:0.165"/>
                            </VisualStateGroup.Transitions>
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="MouseOver"
<Storyboard>
    <DoubleAnimation Duration="0:0:0.165" To="1.25" Storyboard.TargetProperty="(UiElement.RenderTransform).(ScaleTransform.ScaleX)" Storyboard.TargetName="polygon"/>
    <DoubleAnimation Duration="0:0:0.165" To="1.25" Storyboard.TargetProperty="(UiElement.RenderTransform).(ScaleTransform.ScaleY)" Storyboard.TargetName="polygon"/>
    <ColorAnimation Duration="0:0:0.165" To="#FF9BD6FF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/>
    <ColorAnimation Duration="0:0:0.165" To="#FF70ACDF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/>
    <ColorAnimation Duration="0:0:0.165" To="#FF7DAEFF" Storyboard.TargetProperty="(Shape.Stroke).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/>
    <ColorAnimation Duration="0:0:0.165" To="#FF2B5CB4" Storyboard.TargetProperty="(Shape.Stroke).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/>
</Storyboard>
                            </VisualState>
                            <VisualState x:Name="Pressed"/>
                            <VisualState x:Name="Disabled"/>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>


                  <LayoutTransformer
                         LayoutTransform="{Binding Path=ArrowDirection,
                           RelativeSource={RelativeSource TemplatedParent},
                           Converter={StaticResource RotationTranslator_ToBeImplemented}}"
                         Grid.Row="0"
                         HorizontalAlignment="Center">
                    <Polygon
                        x:Name="polygon"

                        Margin="1"
                        StrokeThickness="{TemplateBinding BorderThickness}"

                        RenderTransformOrigin="0.5,0.5">
                        <Polygon.Points>
                            <Point X="10"/>
                            <Point X="0" Y="5" />
                            <Point Y="10" X="10" />
                        </Polygon.Points>
                        <Polygon.RenderTransform>
                            <ScaleTransform />
                        </Polygon.RenderTransform>
                        <Polygon.Fill>
                            <LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1">
                                <GradientStop Color="#FFA9A9A9"/>
                                <GradientStop Color="#FFD3D3D3" Offset="1"/>
                            </LinearGradientBrush>
                        </Polygon.Fill>
                        <Polygon.Stroke>
                            <LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1">
                                <GradientStop Color="#FF696969"/>
                                <GradientStop Color="#FF939393" Offset="1"/>
                            </LinearGradientBrush>
                        </Polygon.Stroke>
                    </Polygon>
                 </LayoutTransformer>


                    <ContentPresenter
                        Grid.Row="1"
                        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

和代码:
public class GlowingArrowButton : ButtonBase
{
    public GlowingArrowButton()
    {
        DefaultStyleKey = typeof (GlowingArrowButton);
    }

    public ArrowDirection ArrowDirection
    {
        get { return (ArrowDirection) GetValue( ArrowDirectionProperty ); }
        set { SetValue( ArrowDirectionProperty, value ); }
    }

    public static readonly DependencyProperty ArrowDirectionProperty =
        DependencyProperty.Register( "ArrowDirection", typeof( ArrowDirection ), typeof( GlowingArrowButton ), new PropertyMetadata( default( ArrowDirection ) ) );
}

public enum ArrowDirection
{
    Left,
    Up,
    Right,
    Down
}

[编辑]
已写但未经测试:
public class RotationTranslator : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var arrowDirection = (ArrowDirection) value;
        switch (arrowDirection)
        {
                case ArrowDirection.Left: return new RotateTransform{ Angle = 0 };

                case ArrowDirection.Up: return new RotateTransform { Angle = 90 };

                case ArrowDirection.Right: return new RotateTransform { Angle = 180 };

                case ArrowDirection.Down: return new RotateTransform { Angle = -90 };
        }
        throw new InvalidOperationException();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){throw new NotSupportedException();}
}

关于xaml - 如何在 Silverlight 5 中使用 VisualStateManager 重用 Storyboard,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10954024/

相关文章:

c# - 将属性绑定(bind)到创建的每个 ListBox.ItemTemplate

c# - 在 C# 中将大十进制值舍入到小十进制值

wpf - xaml 嵌套类路径设计器问题

wpf - 条件 XAML

animation - JavaFX:使用 PathTransition 作为绘图笔的动画

Android 动画方法和可见性 GONE

c#-4.0 - SimpleIoc - 它可以在每次需要时提供新实例吗?

c# - XAML 多重绑定(bind) StringFormat

c# - 从 XAML 中的另一个源文件引用单击方法?

iPhone:UIScrollView 内无限循环内容