前面所介绍的都是单一的动画,它只能修改单一属性。有的时候,我们需要将一组动画一起进行,对于一个按钮,我们可能有如下需求:

  • 选择该按钮时,该按钮增大并更改颜色。
  • 单击该按钮时,该按钮缩小并恢复其原始大小。
  • 该按钮变成禁用时,缩小且不透明度缩减到 50%。

每个操作都同时对应进行着两个动画,此时用我们就需要用到TimelineGroup了,前文介绍TimeLine的时候已经介绍过它了,它可以将多个TimeLine封装成一个统一调度。但TimeLine是一个抽象基类,我们通常使用的是它的子类演示图板(Storyboard)。

演示图板(Storyboard) 是一种为其所包含的时间线提供目标信息的容器时间线。 演示图板可以包含任意类型的 Timeline,包括其他容器时间线和动画。

var widthAnimation = new DoubleAnimation() { To = 250, FillBehavior = FillBehavior.Stop };
    var opacityAnimation = new
DoubleAnimation() { From = 1, To = 0, FillBehavior = FillBehavior.Stop };

var storyBoard = new
Storyboard() { Duration = TimeSpan.FromSeconds(2) };
    storyBoard.Children.Add(widthAnimation);
    storyBoard.Children.Add(opacityAnimation);

Storyboard.SetTargetProperty(widthAnimation, new
PropertyPath("Width"));
    Storyboard.SetTargetProperty(opacityAnimation, new
PropertyPath("Opacity"));

storyBoard.Begin(button);

这个例子简单的演示了如何使用StoryBoard,由于Storyboard经常使用与XAML,这里也介绍一下XAML中的写法:

<Storyboard x:Key="storyBoard">
        <DoubleAnimation Storyboard.TargetProperty="Width" To="250" FillBehavior="Stop"/>
        <DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0" FillBehavior="Stop"/>
    </Storyboard>

使用方式如下:

var storyBoard = this.FindResource("storyBoard") as
Storyboard;
    storyBoard.Begin(button);

比直接用代码编写更加简单。

两个附加属性:

Storyboard.TargetProperty:

由于StoryBoard对应着多个属性的变化,因此不能用UIElement.BeginAnimation的方式执行,而采用Storyboard.TargetProperty附加属性来写入。

Storyboard.TargetName:

Storyboard也可以通知控制多个对象,此时的对象就不能直接在Storyboard.Begin函数中执行,而是通过Storyboard.TargetProperty附加属性写入。

<Storyboard x:Key="storyBoard">
        <DoubleAnimationStoryboard.TargetName="button" Storyboard.TargetProperty="Width" To="250" FillBehavior="Stop"/>
        <DoubleAnimationStoryboard.TargetName="button" Storyboard.TargetProperty="Opacity" From="1" To="0" FillBehavior="Stop"/>
    </Storyboard>

这种方式下,执行storyboard的时候也不用在传入对象了

var storyBoard = this.FindResource("storyBoard") as
Storyboard;
    storyBoard.Begin();

控制Storyboard

前面已经介绍过,Storyboard 像Clock方法一样,直接封装了Begin、 Seek、 Stop、 Pause、Resume、Remove等几个函数,在代码中可以直接使用。另外,在XAML中,Storyboard是可以直接在触发器中(EventTriggerDataTriggerTrigger)使用的,如下就是一个简单的例子:

<Window.Resources>
        <Storyboard x:Key="storyBoard">
            <DoubleAnimation Storyboard.TargetName="button" Storyboard.TargetProperty="Width" To="250" FillBehavior="Stop"/>
            <DoubleAnimation Storyboard.TargetName="button" Storyboard.TargetProperty="Opacity" From="1" To="0" FillBehavior="Stop"/>
        </Storyboard>
    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent="Loaded" >
            <BeginStoryboard Storyboard="{StaticResource storyBoard}" />
        </EventTrigger>
    </Window.Triggers>

可以看到,这儿用到了一个系统提供的名为BeginStoryboard的TriggerAction,同样也提供了SeekStoryboard、 StopStoryboard、 PauseStoryboard、ResumeStoryboard、RemoveStoryboard等几个TriggerAction。一个稍微复杂点的例子如下:

<Window.Resources>
        <Storyboard x:Key="storyBoard">
            <DoubleAnimation Storyboard.TargetName="button" Storyboard.TargetProperty="Width" To="250" FillBehavior="Stop"/>
            <DoubleAnimation Storyboard.TargetName="button" Storyboard.TargetProperty="Opacity" From="1" To="0" FillBehavior="Stop"/>
        </Storyboard>
    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent="MouseEnter" >
            <BeginStoryboard Name="storyBegin" Storyboard="{StaticResource storyBoard}" />
        </EventTrigger>
        <EventTrigger RoutedEvent="MouseLeave" >
            <RemoveStoryboard
BeginStoryboardName="storyBegin" />
        </EventTrigger>
    </Window.Triggers>

另外,微软提供的Interaction也能在XAML中执行Storyboard的控制:

<i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseEnter">
            <ei:ControlStoryboardAction Storyboard="{StaticResource storyBoard}" ControlStoryboardOption="Play" />
        </i:EventTrigger>
        <i:EventTrigger EventName="MouseLeave">
            <ei:ControlStoryboardAction Storyboard="{StaticResource storyBoard}" ControlStoryboardOption="Stop" />
        </i:EventTrigger>
    </i:Interaction.Triggers>

由于微软的Interaction扩展在MVVM模式下非常有用,扩展性也非常好,这种方式很多时候更方便。关于Interaction的使用方式,请参看园子里的这篇文章:Interaction triggers in WPF

参考资料:

演示图板概述

WPF中的动画——(六)演示图板的更多相关文章

  1. WPF中的动画——(三)时间线(TimeLine)

    WPF中的动画——(三)时间线(TimeLine) 时间线(TimeLine)表示时间段. 它提供的属性可以让控制该时间段的长度.开始时间.重复次数.该时间段内时间进度的快慢等等.在WPF中内置了如下 ...

  2. 【WPF学习笔记】[转]周银辉之WPF中的动画 && 晓风影天之wpf动画——new PropertyPath属性链

    (一)WPF中的动画 动画无疑是WPF中最吸引人的特色之一,其可以像Flash一样平滑地播放并与程序逻辑进行很好的交互.这里我们讨论一下故事板. 在WPF中我们采用Storyboard(故事板)的方式 ...

  3. [转]WPF中的动画

    WPF中的动画                                                                                  周银辉 动画无疑是WP ...

  4. (转载)WPF中的动画——(一)基本概念

    http://www.cnblogs.com/TianFang/p/4050845.html WPF的一个特点就是支持动画,我们可以非常容易的实现漂亮大方的界面.首先,我们来复习一下动画的基本概念.计 ...

  5. WPF中的动画

    动画无疑是WPF中最吸引人的特色之一,其可以像Flash一样平滑地播放并与程序逻辑进行很好的交互.这里我们讨论一下故事板. 在WPF中我们采用Storyboard(故事板)的方式来编写动画,为了对St ...

  6. WPF中的动画——(一)基本概念

    WPF的一个特点就是支持动画,我们可以非常容易的实现漂亮大方的界面.首先,我们来复习一下动画的基本概念.计算机中的动画一般是定格动画,也称之为逐帧动画,它通过每帧不同的图像连续播放,从而欺骗眼和脑产生 ...

  7. WPF中的动画——(五)关键帧动画

    与 From/To/By 动画类似,关键帧动画以也可以以动画形式显示目标属性值. 和From/To/By 动画不同的是, From/To/By 动画只能控制在两个状态之间变化,而关键帧动画则可以在多个 ...

  8. WPF中的动画——(五)路径动画

    路径动画是一种专门用于将对象按照指定的Path移动的动画,虽然我们也可以通过控制动画的旋转和偏移实现对象的移动,但路径动画更专业,它的实现更加简洁明了. 路径动画中最常用的是MatrixAnimati ...

  9. WPF中的动画——(二)From/To/By 动画

    我们所实现的的动画中,很大一部分是让一个属性在起始值和结束值之间变化,例如,我在前文中实现的改变宽度的动画: var widthAnimation = new DoubleAnimation()    ...

随机推荐

  1. python基础===继承

    编写类时,并非总是要从空白开始.如果你要编写的类是另一个现成类的特殊版本,可使用继承.一个类继承另一个类时,它将自动获得另一个类的所有属性和方法:原有的类称为父类,而新类称为子类.子类继承了其父类的所 ...

  2. 项目评审ppt的纲要

    1.prd不能模糊,产品的问题全部明确 2.收益在哪里 3.设计体现业务4.怎样保证数据的前后协作5.异常如何处理6.技术解决的痛点7.对外部依赖8.性能指标预期(响应时间)9.

  3. form 表单获取所有数据 封装方法

    function getFormJson(frm) { var o = {}; var a = $(frm).serializeArray(); $.each(a, function () { if ...

  4. Leetcode 之Balanced Binary Tree(49)

    用递归的方式来做,左右两棵子树的高度差不超过1.分成两部分,一部分递归得到树的高度,一部分递归检查左右子树是否是平衡二叉树. int getHeight(TreeNode *root) { ; ; } ...

  5. JAX-RS Resteasy

    JAX-RS (JSR-311) 是为 Java EE 环境下的 RESTful 服务能力提供的一种规范.它能提供对传统的基于 SOAP 的 Web 服务的一种可行替代. https://www.ib ...

  6. 《java并发编程实战》读书笔记3--对象的组合

    希望将一些现有的线程安全组件组合为更大规模的组件或程序 设计线程安全的类 如果对象中所有的域是基本类型变量,那么这些域将构成对象的全部状态.例如,LinkedList的状态就包括该链表中所有节点对象的 ...

  7. hdu 1243(LCS变形)

    反恐训练营 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  8. “无法在web服务器上启动调试,不是Debugger User组成员..."

    在使用VS.net2003开发asp.net项目时,有时候在你调试项目时,会提示”无法在web服务器上启动调试,不是Debugger User组成员..."这样一个错误信息.很是让人头疼,一 ...

  9. Java学习笔记(三)——静态导入,package-info,Fall-through

    [前面的话] 算是真正的放松了好几天时间,没有看任何书,没有任何任务,今天是过完年后的第一天上班时间,我又开始了我的学习之路,感觉还没有老,怎么心态越来越平静了,进入工作状态,就好好努力工作,新的一年 ...

  10. MyBatis插入时候获取自增主键方法

    方法一:(Oralce不支持这种写法) useGeneratedkeys 默认值为 false,含义:设置是否使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty ...