在WPF控件可见性变化时应用动画效果

26

我的XAML是

   <Grid DockPanel.Dock="Top" >
<DockPanel Background="#bdbec0"  MouseEnter="showTopMenu_MouseEnter" HorizontalAlignment="Stretch" Height="55" >                    
    <Button HorizontalAlignment="Center" VerticalAlignment="Center">Down</Button>
</DockPanel>
<DockPanel Background="#151515" LastChildFill="True" Visibility="Collapsed" Name="TopMenuArea"  Height="55">
 some controls here in a horizontal strip , by default its hidden and when some one click on top button its visible and it wil be hidden when some one click outside this area
</DockPanel>

按钮鼠标悬停时的代码为

    private void showTopMenu_MouseEnter(object sender, MouseEventArgs e)
    {          
        TopMenuArea.Visibility = Visibility.Visible;
    }

如何在更改TopMenuArea可见性时应用动画效果?是否有一种直接从XAML中实现的方法?


你要找什么动画? - pushpraj
类似可见度效果或更像不透明度1到0再到0到1。 - Sebastian
6个回答

36

事件触发器

<DockPanel Background="#bdbec0"  MouseEnter="showTopMenu_MouseEnter" HorizontalAlignment="Stretch" Height="55" >
    <DockPanel.Triggers>
        <EventTrigger RoutedEvent="DockPanel.MouseEnter">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="TopMenuArea"
                        From="0.0" To="1.0" Duration="0:0:1"></DoubleAnimation>                            
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
        <EventTrigger RoutedEvent="DockPanel.MouseLeave">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="TopMenuArea"
                        From="1.0" To="0" Duration="0:0:1"></DoubleAnimation>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </DockPanel.Triggers>
    <Button HorizontalAlignment="Center" VerticalAlignment="Center">Down</Button>
</DockPanel>
<DockPanel Background="#151515" LastChildFill="True" Visibility="Collapsed" Opacity="0" Name="TopMenuArea"  Height="55">
</DockPanel>

或者使用淡入淡出的样式(像你之前所做的那样,使用鼠标进入/退出事件处理程序)

<Style TargetType="FrameworkElement" x:Key="VisibleAnimation">
  <Setter Property="Visibility" Value="Collapsed"/>
  <Setter Property="Opacity" Value="0"/>
  <Style.Triggers>
    <Trigger Property="Visibility" Value="Visible">
      <Trigger.EnterActions>
        <BeginStoryboard>
          <Storyboard>
            <DoubleAnimation Storyboard.TargetProperty="Opacity"
                             From="0.0" To="1.0" Duration="0:0:0.2"/>
          </Storyboard>
        </BeginStoryboard>
      </Trigger.EnterActions>
    </Trigger>
  </Style.Triggers>
</Style>

<DockPanel Background="#151515" LastChildFill="True" Style="{StaticResource VisibleAnimation}" Name="TopMenuArea"  Height="55">

只需在应用程序资源中定义样式,或在本地窗口或用户控件中定义。您可以重复使用动画样式以适用于任何控件。

在您的Stackpanel中使用此方法。

<StackPanel Background="Red" HorizontalAlignment="Stretch" >
    <StackPanel.Triggers>
        <EventTrigger RoutedEvent="StackPanel.MouseLeftButtonDown" >
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="TopMenuArea"
                From="1.0" To="0" Duration="0:0:1"></DoubleAnimation>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TopMenuArea"
                        Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame KeyTime="0:0:2" Value="{x:Static Visibility.Collapsed}"/>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </StackPanel.Triggers>
    <Label HorizontalAlignment="Center">Area outside top panel . Clicking here will hide top panel again</Label>
</StackPanel>

只需处理鼠标移出事件,并添加第二个触发器。我会更新我的答案。 - S.L.
1
问题是...当您将可见性设置为折叠时,在此情况下控件在动画开始之前就被隐藏了 :) 但它会将不透明度重置为0。 - S.L.
当我将可见性设置为折叠时,控件在动画开始之前就被隐藏了,因此我无法再次使其可见。 - Sebastian
@JMat ... 更改触发器的顺序。将Collapsed Trigger放在Visible Trigger之前。然后它就可以工作了。 - S.L.
你改了什么吗?它甚至不能使用一个DockPanel。 - S.L.
显示剩余22条评论

19

虽然这个问题已经存在一段时间了,但我已经编写了一个开源库,可以在可见性更改、加载或绑定时实现淡入淡出和/或平移。

您可以在Github上的SciChart.Wpf.UI.TransitionzNuGet上找到它。

用法:

<Window x:Class="WpfApplication15.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:tz="http://schemas.abtsoftware.co.uk/transitionz"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="b2vc"></BooleanToVisibilityConverter>
    </Window.Resources>
    <Grid>
        <CheckBox x:Name="CheckBox" Content="Is Visible?" IsChecked="False"></CheckBox>
        <TextBlock Text="Hello World!" FontSize="44" HorizontalAlignment="Center" VerticalAlignment="Center"
            Visibility="Collapsed"
            tz:Transitionz.Opacity="{tz:OpacityParams From=0, To=1, Duration=200, TransitionOn=Visibility}"
            tz:Transitionz.Translate="{tz:TranslateParams From='10,0', To='0,0', Duration=200, TransitionOn=Visibility}"
            tz:Transitionz.Visibility="{Binding ElementName=CheckBox, Path=IsChecked, Converter={StaticResource b2vc}}"/>
    </Grid>
</Window>

导致以下结果:

在此输入图片描述


6
那个NuGet包真是太棒了,谢谢。 - Askolein
2
太棒了,NuGet..!谢谢。 - Soni Vimalkumar

2

这篇文章会是一个很好的起点。您只需添加一个C#文件,并设置以下属性。

Original Answer翻译成"最初的回答"

common:VisibilityAnimation.AnimationType="Fade" 

1
我想出了一种逐渐显示网格并使用ScaleTransform隐藏网格的方式。
ScaleTransform设置为X=0 Y=0时隐藏,设置为X=1 Y=1时显示,
并使用属性触发器,如下所示代码:
在ViewModel中:
private string _helpVisiblilityTag = "hide";
public string HelpVisiblilityTag
{
    get { return _helpVisiblilityTag; }
    set
    {
        _helpVisiblilityTag = value;
        NotifyOfPropertyChange(() => HelpVisiblilityTag);
    }
}

public void Hide()
{
    HelpVisiblilityTag = "hide";
}
public void Show()
{
    HelpVisiblilityTag = "show";
}

在视图中:
<Button Click="Show"/>



<Grid VerticalAlignment="Center" HorizontalAlignment="Center"  Tag="{Binding HelpVisiblilityTag}" 
              RenderTransformOrigin="0.5, 0.5"  >
    <Grid.Background>
        <SolidColorBrush Color="#D4F1FA" Opacity="0.8"/>
    </Grid.Background>

    <Grid.RenderTransform>
        <ScaleTransform x:Name="MyAnimatedScaleTransform" 
  ScaleX="0" ScaleY="0" />
    </Grid.RenderTransform>

    <Grid.Style>
        <Style TargetType="{x:Type Grid}">
            <Style.Triggers>
                <Trigger Property="Tag" Value="show">
                    <Trigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Opacity"
                         From="0.0" To="1.0" Duration="0:0:1" AutoReverse="False" />
                                <DoubleAnimation
                                Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"  
                                From="0.0" To="1" Duration="0:0:1" AutoReverse="False"
                                 >
                                    <DoubleAnimation.EasingFunction>
                                        <ElasticEase EasingMode="EaseOut" Oscillations="1"/>
                                    </DoubleAnimation.EasingFunction>
                                </DoubleAnimation>
                                <DoubleAnimation
                                Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
                                From="0.0" To="1" Duration="0:0:1" AutoReverse="False"
                                 >
                                    <DoubleAnimation.EasingFunction>
                                        <ElasticEase EasingMode="EaseOut" Oscillations="1"/>
                                    </DoubleAnimation.EasingFunction>
                                </DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.EnterActions>
                    <Trigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Opacity"
                                          Duration="0:0:0.5" AutoReverse="False" />
                                <DoubleAnimation
                                Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
                                From="1" To="0.0" Duration="0:0:0.5" AutoReverse="False"
                                 />
                                <DoubleAnimation
                                Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
                                From="1" To="0.0" Duration="0:0:0.5" AutoReverse="False"
                                 />
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.ExitActions>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Grid.Style>

    <Button Click="Hide"/>

</Grid>

样例截图:

enter image description here


1
这是一个示例例子。
<Grid DockPanel.Dock="Top">
    <DockPanel Background="#bdbec0"
               x:Name="topPanel"
               HorizontalAlignment="Stretch"
               Height="55">
        <Button HorizontalAlignment="Center"
                VerticalAlignment="Center">Down</Button>
    </DockPanel>
    <DockPanel Background="#151515"
               LastChildFill="True"
               Name="TopMenuArea"
               IsHitTestVisible="False"
               Height="55">
        <TextBlock Foreground="White"> some controls here in a horizontal strip , by default its hidden and when some one click on top button its visible and it wil be hidden when some one click outside this area</TextBlock>
        <DockPanel.Style>
            <Style TargetType="DockPanel">
                <Setter Property="Opacity"
                        Value="0" />
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsMouseOver,ElementName=topPanel}"
                                 Value="true">
                        <Setter Property="Opacity"
                                Value="1" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DockPanel.Style>
    </DockPanel>
</Grid>

在上面的示例中,我已经在TopMenuArea dockPanel上设置了IsHitTestVisible="False",因为我可以看到它位于之前的触发面板的顶部。
另一个选项是如果TopMenuArea在顶部,则将其用作源。
示例:
<Grid DockPanel.Dock="Top">
    <DockPanel Background="#bdbec0"
               HorizontalAlignment="Stretch"
               Height="55">
        <Button HorizontalAlignment="Center"
                VerticalAlignment="Center">Down</Button>
    </DockPanel>
    <DockPanel Background="#151515"
               LastChildFill="True"
               Name="TopMenuArea"
               Height="55">
        <TextBlock Foreground="White"> some controls here in a horizontal strip , by default its hidden and when some one click on top button its visible and it wil be hidden when some one click outside this area</TextBlock>
        <DockPanel.Style>
            <Style TargetType="DockPanel">
                <Setter Property="Opacity"
                        Value="0" />
                <Style.Triggers>
                    <Trigger Property="IsMouseOver"
                                 Value="true">
                        <Setter Property="Opacity"
                                Value="1" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </DockPanel.Style>
    </DockPanel>
</Grid>

请试一下,看是否接近你想要的效果。
以上两种方法只是在0和1之间切换不透明度,如果需要,您也可以使用动画来实现淡入淡出效果。

0
您可以使用ToggleButton的选中和未选中路由事件与Event Trigger一起使用:
 <ToggleButton Content="Toggle" Height="20" Width="60" Panel.ZIndex="2" VerticalAlignment="Top" HorizontalAlignment="Left">
        <ToggleButton.Triggers>
            <EventTrigger RoutedEvent="ToggleButton.Checked">
                <BeginStoryboard>
                    <Storyboard >
                        <DoubleAnimation Storyboard.TargetName="MyDockPanel" 
                                         Storyboard.TargetProperty="Opacity"
                                         From="0" To="1" 
                                         Duration="0:0:0.2"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
            <EventTrigger RoutedEvent="ToggleButton.Unchecked">
                <BeginStoryboard>
                    <Storyboard>
                       <DoubleAnimation Storyboard.TargetName="MyDockPanel" 
                                        Storyboard.TargetProperty="Opacity"
                                        From="1" To="0" 
                                        Duration="0:0:0.2"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </ToggleButton.Triggers>
    </ToggleButton>
    <DockPanel x:Name="MyDockPanel"  Background="Yellow" Opacity="0">
        <TextBlock DockPanel.Dock="Bottom" Text="DockPanel" 
                   VerticalAlignment="Center" HorizontalAlignment="Center"/>
    </DockPanel>

结果:

Result


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接