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

时间:2013-10-15 08:42:22

标签: wpf storyboard

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

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

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

这是我目前的代码:

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

希望你能提供帮助:)

3 个答案:

答案 0 :(得分:4)

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

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

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

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

Create a storyboard

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

Duplicating a storyboard

第4步:将此新故事板重命名为您喜欢的内容,例如&#34; Storyboard1_Rev&#34;。

Renaming the newly created storyboard

Storyboard with new name

第5步:你现在必须猜到了。选择重复的故事板,然后从下拉菜单中单击&#34;反向&#34;。

Reversing the storyboard

第6步:现在您已准备好两个故事板:一个用于动画一些元素,另一个用于反转动画序列。就像您从C#代码调用故事板一样,您可以根据某些条件调用可逆故事板,这些条件会检查元素是否已经设置了动画。为此,我使用bool变量,每次在一组元素上发生某些动画时,其值都会更改(即,如果元素尚未设置动画,则为false;如果是动画,则为true)。

插图示例:

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

Initial screen layout

这个想法是,无论何时单击按钮一次,图像应该最大化,并且当按下按钮两次时应该最小化回原始尺寸,依此类推。也就是说,每按一次按钮就会发生反向动画。以下是一些屏幕截图,展示了它是如何发生的:

Initial Zooming in Zoomed in Zooming out Zoomed out

您可以看到图像的当前状态显示在按钮中。它显示&#34;放大&#34;当图像处于其初始的小尺寸时,&#34;缩小&#34;当它最大化时。

最后,这是用于处理按钮点击的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;
        }
    }

您所要做的就是拥有一个状态标志,该状态标志显示您希望设置的元素的当前状态,并根据标志的值在正向或反向时间轴中为它们(它们)设置动画。

答案 1 :(得分:0)

而不是尝试使用该事件设置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时,第二个将开始。

答案 2 :(得分:0)

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

为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);
        }
    }