WPF故事板-相同的触发器,但行为相反

WPF故事板-相同的触发器,但行为相反,wpf,storyboard,Wpf,Storyboard,我有一个Stackpanel,它有一些内容、一个图像和一个解除隐藏的SubStackpanel。在图像中单击时,图像应旋转90度,并向下滑动子背景面板。 再次单击图像时,图像应旋转回其原始位置,并且子堆栈面板应向上滑动到默认隐藏位置 我几乎成功了,问题是我不知道如何在两个不同的故事板动画上使用相同的触发事件。所以现在只有按钮和SubStackpanel上的第一个动画出现,每次单击图像时。 我尝试了自动翻转属性,但它在动画完成后立即触发。当然,这应该只在用户第二次单击图像时发生 我想实现这一点,只

我有一个Stackpanel,它有一些内容、一个图像和一个解除隐藏的SubStackpanel。在图像中单击时,图像应旋转90度,并向下滑动子背景面板。 再次单击图像时,图像应旋转回其原始位置,并且子堆栈面板应向上滑动到默认隐藏位置

我几乎成功了,问题是我不知道如何在两个不同的故事板动画上使用相同的触发事件。所以现在只有按钮和SubStackpanel上的第一个动画出现,每次单击图像时。 我尝试了自动翻转属性,但它在动画完成后立即触发。当然,这应该只在用户第二次单击图像时发生

我想实现这一点,只使用标记

这是我当前的代码:

<Grid>
        <StackPanel Grid.Row="0" Orientation="Vertical" Background="Beige" >
            <StackPanel.Triggers>
                <EventTrigger SourceName="ImageShowPanelTwo" RoutedEvent="Image.MouseDown">
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="SubPanel" Storyboard.TargetProperty="(StackPanel.Height)" From="0" To="66" Duration="0:0:0.5" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
                <EventTrigger  SourceName="ImageShowPanelTwo" RoutedEvent="Image.MouseDown">
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="SubPanel" Storyboard.TargetProperty="(StackPanel.Height)" From="66" To="0" Duration="0:0:0.5" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </StackPanel.Triggers>

            <TextBlock>Panel One</TextBlock>

            <Image Name="ImageShowPanelTwo" Width="26" Height="26" Source="ImageRotate.png" RenderTransformOrigin=".5,.5"  >
                <Image.RenderTransform>
                    <RotateTransform x:Name="AnimatedRotateTransform" Angle="0" />
                </Image.RenderTransform>
                <Image.Triggers>
                    <EventTrigger RoutedEvent="Image.MouseDown">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetName="AnimatedRotateTransform" 
                                             Storyboard.TargetProperty="Angle" 
                                             By="0"        
                                             To="90" 
                                             Duration="0:0:0.5" 
                                                 AutoReverse="True"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="Image.MouseDown">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetName="AnimatedRotateTransform" 
                                             Storyboard.TargetProperty="Angle" 
                                             By="90"        
                                             To="0" 
                                             Duration="0:0:0.5" 
                                                 AutoReverse="True"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </Image.Triggers>
            </Image>


            <StackPanel Name="SubPanel" Background="LightGreen" Height="66">
                <TextBlock>SubPanel</TextBlock>
                <TextBlock>SubPanel</TextBlock>
            </StackPanel>

        </StackPanel>


    </Grid>

第一小组
副面板
副面板

希望您能提供帮助:)

不要尝试使用该事件设置
动画,而是使用
bool
属性绑定:

<Image Name="ImageShowPanelTwo" Width="26" Height="26" Source="ImageRotate.png" 
    RenderTransformOrigin=".5,.5"  >
    <Image.RenderTransform>
        <RotateTransform x:Name="AnimatedRotateTransform" Angle="0" />
    </Image.RenderTransform>
    <Image.Style>
        <Style>
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsRotated}" Value="True">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation 
                                    Storyboard.TargetName="AnimatedRotateTransform" 
                                    Storyboard.TargetProperty="Angle" 
                                    By="0"        
                                    To="90" 
                                    Duration="0:0:0.5" 
                                    AutoReverse="True"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
                <DataTrigger Binding="{Binding IsRotated}" Value="False">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation 
                                    Storyboard.TargetName="AnimatedRotateTransform" 
                                    Storyboard.TargetProperty="Angle" 
                                    By="90"        
                                    To="0" 
                                    Duration="0:0:0.5" 
                                    AutoReverse="True"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Image.Style>
</Image>


我相信您可以定义自己的
bool
属性,并在每次
MouseDown
事件发生时将其反转以完成此功能。当设置为
true
时,第一个
动画将启动,当设置为
false
时,第二个将启动。

这就是我解决问题的方法:

为Stackpanel和箭头创建了四个故事板:

<Storyboard x:Key="RotateIconUp">
            <DoubleAnimation Storyboard.TargetName="IconExpand" Storyboard.TargetProperty="(TextBlock.RenderTransform).(RotateTransform.Angle)" From="0" To="90" Duration="0:0:0.4" />
        </Storyboard>
        <Storyboard x:Key="RotateIconDown">
            <DoubleAnimation Storyboard.TargetName="IconExpand" Storyboard.TargetProperty="(TextBlock.RenderTransform).(RotateTransform.Angle)" From="90" To="0" Duration="0:0:0.4" />
        </Storyboard>
        <Storyboard x:Key="SlideGridDown">
            <DoubleAnimation Storyboard.TargetName="GridDetails" Storyboard.TargetProperty="(Grid.Height)" From="0" To="180" Duration="0:0:0.4" />
        </Storyboard>
        <Storyboard x:Key="SlideGridUp">
            <DoubleAnimation Storyboard.TargetName="GridDetails" Storyboard.TargetProperty="(Grid.Height)" From="180" To="0" Duration="0:0:0.4" />
        </Storyboard>

Blend for Visual Studio可以用一种更好、更简单的方法来实现,而无需处理大量代码

下面是执行此操作的步骤列表

步骤1:同时在Blend for Visual Studio和Visual Studio中打开项目

步骤2:在“混合”中,围绕要使用它制作动画的所有元素创建一个新的故事板。 让我们称之为“故事板1”

步骤3:现在,打开我们刚刚创建的故事板,单击“+”旁边的小箭头,然后单击下拉菜单中的“复制”。然后,将创建一个名为“Storyboard1_Copy”的新故事板

步骤4:将此新情节提要重命名为您喜欢的内容,例如,“情节提要1\u Rev”

步骤5:你现在一定猜到了。选择复制的故事板,然后从下拉菜单中单击“反转”

步骤6:现在有两个故事板准备就绪:一个用于根据需要设置某些元素的动画,另一个用于反转动画序列。就像从C#代码中调用情节提要一样,您也可以从相同的代码中调用反转情节提要,但需要满足一些条件,以检查元素是否已设置动画。为此,我使用了一个bool变量,每当一组元素上出现动画时,该变量的值都会改变(即,如果元素尚未设置动画,则为false;如果元素已设置动画,则为true)

举例说明:

我将创建一个布局简单的应用程序。它在屏幕上有一个按钮、一个图像和一个矩形区域

这个想法是,每当你点击按钮一次,图像应该被最大化,当按钮被点击两次时,图像应该被最小化回到原始大小,以此类推。也就是说,每次单击按钮时都应该发生反向动画。以下是一些屏幕截图,显示了它是如何发生的:

您可以看到按钮中显示了图像的当前状态。当图像处于初始小尺寸时显示“放大”,当图像最大化时显示“缩小”

最后,这里是处理按钮点击的C代码:

    bool flag = false;
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (!flag)
        {
            Button.Content = "Zoom Out";
            Storyboard1.Begin();
            flag = true;
        }
        else
        {
            Button.Content = "Zoom In";
            Storyboard1_Rev.Begin();
            flag = false;
        }
    }

您所要做的就是设置一个状态标志,显示您希望设置动画的元素的当前状态,并根据该标志的值在正向或反向时间线上设置动画。

非常感谢您的回答!:)我已经尝试了你的代码,但我得到一个错误:不能在样式设置器上设置TargetName属性。-我已经对此进行了调查,似乎这是一个范围问题,因为这是在一个样式中定义的?此外,我不知道您的解决方案是否有效,因为我只想在XAML标记中实现这一点。因为我想在资源中定义这种行为,并在其他地方使用它。这意味着我不能在代码隐藏中定义bool并将其用作绑定:(啊..我们有两个问题…第一个是t
    bool flag = false;
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (!flag)
        {
            Button.Content = "Zoom Out";
            Storyboard1.Begin();
            flag = true;
        }
        else
        {
            Button.Content = "Zoom In";
            Storyboard1_Rev.Begin();
            flag = false;
        }
    }