4

我有一个 Stackpanel One,它有一些内容、一个图像和一个默认隐藏的 SubStackpanel。单击图像时,图像应旋转 90 度,然后滑下 SubStackpanel。再次单击 Image 时,Image 应旋转回其原始位置,并且 SubStackpanel 应向上滑动到默认隐藏位置。

我几乎得到了这个工作,问题是我不知道如何在两个不同的故事板动画上使用相同的触发事件。因此,现在每次单击图像时,只会出现按钮和 SubStackpanel 上的第一个动画。我试过 AutoReverse 属性,但它在动画完成后立即触发。这当然应该只在用户第二次单击图像时发生。

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

这是我目前的代码:

<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>

希望你能帮忙:)

4

3 回答 3

4

Blend for Visual Studio 可用于以更好、更简单的方式完成此任务,而无需处理大量代码。

这是执行此操作的步骤列表。

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

第 2 步:在 Blend 中,围绕您希望使用它制作动画的所有元素创建一个新的故事板。我们称它为“Storyboard1”。

创建故事板

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

复制故事板

第 4 步:将这个新故事板重命名为您喜欢的名称,例如“Storyboard1_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;
        }
    }

您所要做的就是有一个状态标志,它显示您希望动画的元素的当前状态,并根据标志的值在正向或反向时间轴中对其(它们)进行动画处理。

于 2014-10-10T12:52:58.207 回答
1

与其尝试设置Animation使用该事件,不如使用一个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第一个Animation将启动,设置为false第二个将启动。

于 2013-10-15T09:03:44.773 回答
1

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

为 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>

然后我在单击箭头时从代码隐藏触发情节提要:

private void ExpandDetails() {
        try {
            if (!pm_IsExanded) {
                Storyboard Storyboard = (Storyboard)FindResource("RotateIconUp");
                Storyboard.Begin(this);
                Storyboard = (Storyboard)FindResource("SlideGridDown");
                Storyboard.Begin(this);
                pm_IsExanded = true;
                BorderMain.BorderBrush = pm_BrushConverter.ConvertFromString("#000000") as Brush;
            } else {
                Storyboard Storyboard = (Storyboard)FindResource("RotateIconDown");
                Storyboard.Begin(this);
                Storyboard = (Storyboard)FindResource("SlideGridUp");
                Storyboard.Begin(this);
                pm_IsExanded = false;
                BorderMain.BorderBrush = pm_BrushConverter.ConvertFromString("#d0d0d0") as Brush;
            }
        } catch (Exception ee) {
            GlobalResource.WriteToLog("Error in ExpandDetails", ee);
        }
    }
于 2013-10-21T07:38:53.910 回答