使用 wpf VisualStateManager 动画可见性和不透明度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12301479/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Animating visibility AND opacity with wpf VisualStateManager
提问by lycilph
I am trying to animate a control so that it's visibility is set to visible then animating the opacity from 0 to 1
我正在尝试为控件设置动画,以便将其可见性设置为可见,然后将不透明度从 0 设置为 1
However nothing happens, then after 1 second the control is show with an opacity of 1... I cannot see what i am doing wrong
然而什么也没有发生,然后在 1 秒后控件显示为 1 的不透明度......我看不出我做错了什么
This is the code i have tried
这是我试过的代码
<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>
回答by dtm
As to the question of what you're doing wrong or why you see the behavior that you see: the storyboard for the Enabled state is the storyboard that the VSM uses while the VSGroup is inthat state. You specify a transition storyboard for the group, though, and the VSM applies that when transitioning betweenstates. So, when you put the VSGroup into the Enabled state, the VSM first plays the transition storyboard then uses the steady-state storyboard that you specify for the Enabled state. The transition storyboard is 1 sec, and that's why you're seeing the 1 sec delay and then the pop.
至于您做错了什么或为什么会看到您看到的行为的问题:启用状态的故事板是 VSM 在 VSGroup处于该状态时使用的故事板。不过,您可以为该组指定一个转换故事板,并且 VSM在状态之间转换时会应用该故事板。因此,当您将 VSGroup 置于 Enabled 状态时,VSM 首先播放过渡情节提要,然后使用您为启用状态指定的稳态情节提要。过渡情节提要为 1 秒,这就是为什么您会看到 1 秒延迟然后弹出。
Something like the following is probably what you want. Note that the transition storyboard does the action/animation that you want, and the state storyboards just state the final values at which the animated properties should be held. Also, I apply the easing function to the double animation rather than to the entire VisualTransition -- it doesn't make sense to try to interpolate Visibility with an easing function.
像下面这样的东西可能是你想要的。请注意,过渡情节提要执行您想要的动作/动画,而状态情节提要仅说明应保持动画属性的最终值。此外,我将缓动函数应用于双动画而不是整个 VisualTransition —— 尝试用缓动函数插入可见性是没有意义的。
<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>
回答by Trevor Elliott
The Visibility enum is not an inherently animatable property. Generally only numeric properties are truly animatable, since WPF can fill in the spaces between keyframes. For example, it knows that an opacity halfway between the value of 0 and 1 is 0.5. It knows every possible value based on the current time.
Visibility 枚举不是一个固有的动画属性。通常只有数字属性是真正可动画的,因为 WPF 可以填充关键帧之间的空间。例如,它知道介于 0 和 1 之间的不透明度是 0.5。它知道基于当前时间的每个可能的值。
If you animate from Visibility.Collapsed to Visibility.Visible over 1 second, it has no idea what to do at the 0.5 second mark or any other point in between. It only knows you're changing an enum from 1 value to another. If your transition time is 1 second, it waits till that second is up and then changes the value, so you never get to see the opacity animation happening.
如果您在 1 秒内从 Visibility.Collapsed 到 Visibility.Visible 进行动画处理,则它不知道在 0.5 秒标记处或两者之间的任何其他点要做什么。它只知道您正在将枚举从 1 值更改为另一个值。如果你的过渡时间是 1 秒,它会等到那一秒结束然后改变值,所以你永远看不到不透明度动画的发生。
You can try using FluidLayout. You enable it like so:
您可以尝试使用 FluidLayout。您可以像这样启用它:
<VisualStateGroup x:Name="Filtering" ei:ExtendedVisualStateManager.UseFluidLayout="True">
You can also enable it using a toggle in the Blend UI.
您还可以使用 Blend UI 中的切换来启用它。
FluidLayout animates layout changes for you. Collapsing or expanding an element affects the layout, so it can automatically animate those layout changes.
FluidLayout 为您动画布局更改。折叠或展开元素会影响布局,因此它可以自动为这些布局更改设置动画。

