使用wpf VisualStateManager为可见性和不透明度设置动画

时间:2012-09-06 13:43:44

标签: wpf animation storyboard transition visualstatemanager

我正在尝试为控件设置动画,以便将其可见性设置为可见,然后将不透明度从0设置为1

然而没有任何反应,那么在1秒之后,控件显示的不透明度为1 ......我看不出我做错了什么

这是我试过的代码

<Grid x:Name="layout_root" Margin="10">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="Filtering">
            <VisualStateGroup.Transitions>
                <VisualTransition GeneratedDuration="0:0:1">
                    <VisualTransition.GeneratedEasingFunction>
                        <ElasticEase EasingMode="EaseInOut"/>
                    </VisualTransition.GeneratedEasingFunction>
                </VisualTransition>
            </VisualStateGroup.Transitions>

            <VisualState x:Name="Disabled"/>
            <VisualState x:Name="Enabled">
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames BeginTime="0:0:0" Duration="0:0:0" Storyboard.TargetName="filter_control" Storyboard.TargetProperty="(UIElement.Visibility)">
                        <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}"/>
                    </ObjectAnimationUsingKeyFrames>
                    <DoubleAnimation Storyboard.TargetName="filter_control" Storyboard.TargetProperty="(UIElement.Opacity)" To="1"/>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
    </Grid.RowDefinitions>

    <TextBox x:Name="filter_control" Margin="0,0,0,10" Text="Filtering" Visibility="Collapsed" Opacity="0"/>

    <ListView Grid.Row="1" ItemsSource="{Binding Posts}">
        <ListView.View>
            <GridView>
                <GridViewColumn Width="100" Header="Date" DisplayMemberBinding="{Binding Date, StringFormat={}{0:dd/MM/yyyy}}"/>
                <GridViewColumn Width="100" Header="Text" DisplayMemberBinding="{Binding Text}"/>
                <GridViewColumn Width="100" Header="Value" DisplayMemberBinding="{Binding Value, StringFormat=F2}"/>
            </GridView>
        </ListView.View>
    </ListView>

    <Button Grid.Row="1" Content="v" FontFamily="Marlett" FontSize="14" VerticalAlignment="Top" HorizontalAlignment="Left" Click="ShowFilterClick"/>
</Grid>

2 个答案:

答案 0 :(得分:3)

关于你做错了什么或者为什么你看到你看到的行为的问题:启用状态的故事板是VSM使用的故事板,而VSGroup是 州。但是,您为该组指定了转换故事板,并且在状态之间转换时,VSM会应用该故事板。因此,当您将VSGroup置于启用状态时,VSM首先播放转换故事板,然后使用您为启用状态指定的稳态故事板。转换故事板是1秒,这就是为什么你看到1秒的延迟然后是流行音乐。

以下内容可能就是您想要的。请注意,转换故事板会执行您需要的操作/动画,状态故事板只是说明应该保留动画属性的最终值。此外,我将缓动函数应用于双动画而不是整个VisualTransition - 尝试使用缓动函数插入Visibility没有意义。

<VisualStateGroup x:Name="Filtering">
    <VisualStateGroup.Transitions>
        <VisualTransition From="Disabled" To="Enabled" GeneratedDuration="0:0:1">
            <Storyboard>
               <ObjectAnimationUsingKeyFrames Duration="0:0:0" Storyboard.TargetName="filter_control" Storyboard.TargetProperty="(UIElement.Visibility)">
                   <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}"/>
               </ObjectAnimationUsingKeyFrames>
               <DoubleAnimation Duration="0:0:1" Storyboard.TargetName="filter_control" Storyboard.TargetProperty="(UIElement.Opacity)" To="1">
                  <DoubleAnimation.EasingFunction>
                     <ElasticEase EasingMode="EaseInOut"/>
                  </DoubleAnimation.EasingFunction>
               </DoubleAnimation>
           </Storyboard>
       </VisualTransition>
       <!-- you could also have a transition from Enabled to Disabled -->
    </VisualStateGroup.Transitions>

    <VisualState x:Name="Disabled">
            <Storyboard>
               <ObjectAnimationUsingKeyFrames Duration="0:0:0" Storyboard.TargetName="filter_control" Storyboard.TargetProperty="(UIElement.Visibility)">
                   <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}"/>
               </ObjectAnimationUsingKeyFrames>
               <DoubleAnimation Duration="0:0:0" Storyboard.TargetName="filter_control" Storyboard.TargetProperty="(UIElement.Opacity)" To="0"/>
           </Storyboard>
    </VisualState>
    <VisualState x:Name="Enabled">
            <Storyboard>
               <ObjectAnimationUsingKeyFrames Duration="0:0:0" Storyboard.TargetName="filter_control" Storyboard.TargetProperty="(UIElement.Visibility)">
                   <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}"/>
               </ObjectAnimationUsingKeyFrames>
               <DoubleAnimation Duration="0:0:0" Storyboard.TargetName="filter_control" Storyboard.TargetProperty="(UIElement.Opacity)" To="1"/>
           </Storyboard>
    </VisualState>
</VisualStateGroup>

答案 1 :(得分:1)

可见性枚举不是固有的可动画属性。通常只有数字属性才是真正可动画的,因为WPF可以填充关键帧之间的空格。例如,它知道0和1之间的不透明度是0.5。它根据当前时间知道每个可能的值。

如果您在1秒钟内从Visibility.Collapsed到Visibility.Visible进行动画制作,则它不知道在0.5秒标记或其间任何其他点处做什么。它只知道你将枚举从1值更改为另一个值。如果您的转换时间是1秒,它会等到第二个启动然后更改值,这样您就不会看到不透明度动画发生了。

您可以尝试使用FluidLayout。你这样启用它:

<VisualStateGroup x:Name="Filtering" ei:ExtendedVisualStateManager.UseFluidLayout="True">

您也可以使用Blend UI中的切换启用它。

FluidLayout为您设置布局更改动画。折叠或展开元素会影响布局,因此它可以自动设置这些布局更改的动画。