我正在创建一个包含动画的样式,然后可以将其继承为自动应用的特定控件样式。
实际上,我正在努力实现一个简单的动画:
- 当
Visibility
更改为Visible
时,Opacity
从 0 更改为 1 - 当
Visibility
更改为visible
以外的其他东西时,Opacity
正在做相反的事情
到目前为止,我得到了:
<Style x:Key="BaseAnimationsStyle">
<Style.Triggers>
<Trigger Property="FrameworkElement.Visibility" Value="Visible">
<Trigger.EnterActions> <!-- this works -->
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions><!-- this doesn't -->
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
如果在控件上设置了上述样式,则它具有以下行为:
当控件的Visibility
设置为Visible
时,过渡工作正常,这意味着它正在淡入。
问题:当控件的Visibility
设置为 Hidden
(甚至Collapsed
(时,控件将立即隐藏而不会褪色。
我的猜测是,在FrameworkElement
处理可见性更改的方式中,有一些默认行为需要覆盖。
Visibility
属性设置为 Collapsed
或 Hidden
将使元素立即不可见,但您可以设置您的一些附加属性,然后对 Opacity
属性进行动画处理以淡出元素,而不是设置 Visibility
属性。请参阅以下链接以获取更多信息和示例。
WPF:如何对可见性属性进行动画处理?:
WPF 淡入淡出动画
我已经用@mm8的答案提供的信息解决了我的问题。
基本上,我将可见性动画类添加到我的项目中。然后,我只是使用在 Setter 中提供的附加属性创建了我的基本样式。
<!-- Animations -->
<Style x:Key="BaseAnimationsStyle">
<Setter Property="anim:VisibilityAnimation.AnimationType" Value="Fade" />
</Style>
<!-- This adds the Visibility Animation to every Grid which has access to this resource -->
<Style TargetType="{x:Type Grid}" BasedOn="{StaticResource BaseAnimationsStyle}" />
另一种解决方案:
为可见性创建附加属性。这使您能够设置任何控件的可见性,而无需自动设置不透明度。
如果要对属性使用 Bindings,则绑定的第一次计算会导致动画(如果值未Visibility.Visible
。这就是为什么需要另一个属性来指定另一个可见性来启动的原因。
public static class AnimateableVisibility
{
public static readonly DependencyProperty VisibilityProperty = DependencyProperty.RegisterAttached(
"Visibility", typeof(Visibility), typeof(AnimateableVisibility), new PropertyMetadata(default(Visibility), VisibilityPropertyChanged));
private static void VisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var val = (Visibility) e.NewValue;
// Set StartVisibility to Visible when Visibility is set to Visible
if (val == Visibility.Visible)
d.SetCurrentValue(StartVisibilityProperty, val);
}
public static readonly DependencyProperty StartVisibilityProperty = DependencyProperty.RegisterAttached(
"StartVisibility", typeof(Visibility), typeof(AnimateableVisibility), new PropertyMetadata(default(Visibility)));
public static Visibility GetVisibility(DependencyObject obj)
{
return (Visibility)obj.GetValue(VisibilityProperty);
}
public static void SetVisibility(DependencyObject obj, Visibility value)
{
obj.SetValue(VisibilityProperty, value);
}
public static Visibility GetStartVisibility(DependencyObject obj)
{
return (Visibility)obj.GetValue(VisibilityProperty);
}
public static void SetStartVisibility(DependencyObject obj, Visibility value)
{
obj.SetValue(VisibilityProperty, value);
}
}
现在,您可以按如下方式使用这些属性:
<Grid>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Orientation="Horizontal">
<Button Margin="5,0,15,0" Padding="7,0" Style="{StaticResource VisibilityAnimation}" utils:AnimateableVisibility.StartVisibility="Hidden"
utils:AnimateableVisibility.Visibility="{Binding ElementName=CheckBox, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}">I'm a Button</Button>
<CheckBox VerticalAlignment="Center" IsChecked="False" x:Name="CheckBox"></CheckBox>
</StackPanel>
</Grid>
通过将StartVisibility
更改为 Visible
,您可以看到Button
在启动时如何淡出。
现在缺少的只是应用的样式:
<Style x:Key="VisibilityAnimation">
<Style.Triggers>
<Trigger Property="utils:AnimateableVisibility.StartVisibility" Value="Hidden">
<!-- This avoids the Animation in cases when the first evaluation of AnimateableVisibility.Visibility is false -->
<Setter Property="UIElement.Visibility" Value="Hidden" />
</Trigger>
<Trigger Property="utils:AnimateableVisibility.Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard TargetProperty="Opacity">
<DoubleAnimation To="1" Duration="0:0:2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard TargetProperty="Opacity">
<DoubleAnimation To="0" Duration="0:0:2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>