本文告诉大家,在后台代码,对 TranslateTransform 做动画的方法

今天小伙伴问我一个问题,说为什么相同的代码,如果设置到按钮上,是可以让按钮的某个属性变更,但是如果设置给 TranslateTransform 的 X 或 Y 就不会有任何值变更

在 WPF 中,通过 官方文档 里面的描述,对于 Freezable 类型的对象,如 SolidColorBrush 和 RotateTransform 和 GradientStop 等类型,都是不支持直接的动画,也就是如以下代码是不能触发动画

假定有 XAML 界面如下,期望在点击按钮时,修改按钮的 TranslateTransform 做动画

  <Grid>
<Button x:Name="Button" HorizontalAlignment="Center" VerticalAlignment="Center" Content="按钮" Click="Button_OnClick">
<Button.RenderTransform>
<TranslateTransform x:Name="ButtonTranslateTransform"></TranslateTransform>
</Button.RenderTransform>
</Button>
</Grid>

如果直接对使用 Storyboard 的 SetTarget 方法给对象设置 DoubleAnimation 将会是无效的,也就是说如以下的代码做的 TranslateTransform 动画是无效的,没有反应的

        private void Button_OnClick(object sender, RoutedEventArgs e)
{
var storyboard = new Storyboard(); var doubleAnimation = new DoubleAnimation();
Storyboard.SetTarget(doubleAnimation, ButtonTranslateTransform);
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath(TranslateTransform.XProperty)); doubleAnimation.To = 100;
doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(2)); storyboard.Children.Add(doubleAnimation);
storyboard.Begin();
}

如果想要给 Freezable 类型的对象做动画,可以通过间接的方法,也就是通过 Freezable 类型的对象所在的元素,使用点的方式写出来具体的代码

        private void Button_OnClick(object sender, RoutedEventArgs e)
{
var storyboard = new Storyboard(); var doubleAnimation = new DoubleAnimation();
Storyboard.SetTarget(doubleAnimation, Button);
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)")); doubleAnimation.To = 100;
doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(2)); storyboard.Children.Add(doubleAnimation);
storyboard.Begin();
}

写法就是通过某个元素的某个属性加上某个类型的某个属性。如上面代码使用的是 UIElement 的 RenderTransform 属性,这个属性的值的类型是 TranslateTransform 类型,设置这个类型的 X 属性

上面的 PropertyPath 有可以换成如下方式写

            var propertyChain = new object[]
{
UIElement.RenderTransformProperty,
TranslateTransform.XProperty
}; Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(0).(1)", propertyChain));

我更推荐使用这个写法,因为这样就不会写错命名

而如果只是为了修改 TranslateTransform 的 X 属性,最简单的写法就是通过 BeginAnimation 的方式,如下面代码

        private void Button_OnClick(object sender, RoutedEventArgs e)
{
ButtonTranslateTransform.BeginAnimation(TranslateTransform.XProperty, new DoubleAnimation()
{
To = 100,
Duration = new Duration(TimeSpan.FromSeconds(1))
});
}

以上代码可以看到很清真

这里的 Duration 其实可以通过 TimeSpan 转换,而不需要创建 Duration 对象。然而在 WPF 依然定义 Duration 类的原因是为了支持 Duration.Automatic 和 Duration.Forever 特殊的定义

如果是需要有多个属性开始做动画,不想使用 BeginAnimation 的方式,可以通过在后台代码用 SetTargetName 的方法指定,如下面代码

        private void Button_OnClick(object sender, RoutedEventArgs e)
{
var storyboard = new Storyboard(); var doubleAnimation = new DoubleAnimation();
Storyboard.SetTargetName(doubleAnimation, nameof(ButtonTranslateTransform));
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath(TranslateTransform.XProperty)); doubleAnimation.To = 100;
doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(2)); var storyboardName = "s" + storyboard.GetHashCode();
// 加入到字典,让 Storyboard 和 ButtonTranslateTransform 在相同的一个 NameScope 里
Resources.Add(storyboardName, storyboard); storyboard.Children.Add(doubleAnimation);
storyboard.Begin();
}

在后台代码做动画,如果使用 SetTargetName 就需要让 Storyboard 和对应的元素在相同的一个 NameScope 里,不然将会提示 System.InvalidOperationException 不存在可解析名称“xx”的适用名称领域,如下面代码

System.InvalidOperationException:“不存在可解析名称“ButtonTranslateTransform”的适用名称领域。”

上面代码通过将动画加入到资源字典的方式,让动画和元素在相同的 NameScope 而让动画能找到元素。但是上面代码将会在资源字典加入一个 Storyboard 而没有释放,如果在你的实际代码,我推荐在动画完成之后,删除资源字典的动画

我特别翻了 WPF 编程宝典,发现宝典里面没有这部分知识,也就是没有告诉大家为什么直接给 TranslateTransform 的属性做动画将会失效。好在官方文档里面有说到这点

本文代码还请到 githubgitee 上阅读代码

可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 78f63c1c076065d1891559f5af2cb29f10a39f8b

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git

获取代码之后,进入 KayceefiwhearHaijanihukere 文件夹

Storyboards Overview - WPF .NET Framework

WPF 后台代码做 TranslateTransform 的动画的更多相关文章

  1. How do I duplicate a resource reference in code behind in WPF?如何在WPF后台代码中中复制引用的资源?

    原文 https://stackoverflow.com/questions/28240528/how-do-i-duplicate-a-resource-reference-in-code-behi ...

  2. WPF后台代码实现TextBlock滚动条

    方法一: 常规的WPF操作: <ScrollViewer Width=" VerticalScrollBarVisibility="Auto" Horizontal ...

  3. C# Wpf 后台代码设定UIElement的Canvas位置属性值

    后台in-code设定元件UIElement的Canvas位置属性的两种方法: 1.UIElement.SetValue()方法 uiElement.SetValue(Canvas.TopProper ...

  4. 7.7 WPF后台代码绑定如果是属性,必须指定一下数据上下文才能实现,而函数(click)就不用

    如: private bool _IsExportWithImage; /// <summary> /// 是否选择导出曲线图 /// </summary> public bo ...

  5. WPF MVVM 架构 Step By Step(4)(添加bindings - 完全去掉后台代码)

    之前的改进已经挺棒的,但是我们现在知道了后台代码的问题,那是否可能把后台代码全部去除呢?这时候就该WPF binding 和 commands 来做的事情了. WPF就是以超吊的binding,com ...

  6. WPF后台动画DoubleAnimation讲解

    WPF后台动画,使用DoubleAnimation做的. 1.移动动画 需要参数(目标点离最上边的位置,目标点离最左边的位置,元素名称) Image mImage = new Image(); Flo ...

  7. WPF内嵌代码和后台代码简单混合使用

    下面实例展示了WPF内嵌代码和后台代码混合使用,一个简单基础的实例: xaml文件: <Window x:Class="WPF内嵌代码和后台代码混合使用.MainWindow" ...

  8. WPF MVVM 架构 Step By Step(3)(把后台代码移到一个类中)

    我觉得大部分开发者应该已经知道怎么去解决这个问题.一般都是把后台代码(GLUE code)移动到一个类库.这个类库用来代表UI的属性和行为.任何代码当被移到一个类库中时都可以被编译成一个DLL,然后可 ...

  9. wpf 分别用 xaml 和后台代码实现 色彩渐变

    xaml 方法: <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.micros ...

随机推荐

  1. Android持续优化 - 提高流畅度

    http://www.cnblogs.com/purediy/archive/2013/12/26/3492865.html

  2. <JVM下篇:性能监控与调优篇>补充:浅堆深堆与内存泄露

    笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...

  3. java之Map的使用

    Map的实现类有很多,其中较为常见的有HashMap,HashTable,LinkedHashMap,TreeMap,下面分别对这几个类进行简单的分析: 1.HashMap HashMap的结构数组+ ...

  4. nginx 配置后页面访问是报500错

    该问题是html文件权限问题. 用jenkins 并远程服务器上传到另一台服务器的html ,在配置好nginx 的location  root 绝对位置后还是报错500 手工用root上传时访问正常 ...

  5. 数据人必读!玩转数据可视化用这个就够了——高德LOCA API 2.0升级来袭!

    引言 "一图胜千言",大数据时代来临,数据与人们生活密切相关.复杂难懂且体量庞大的数据给人的感觉总是冷冰冰的,让人难以获取到重点信息,也找不出规律和特征,数据价值发挥不出来.空间数 ...

  6. [BUAA2021软工]结对第一阶段博客作业小结

    作业链接 结对项目-第一阶段 优秀作业推荐 本次博客作业虽然是简单总结,但是以下作业中都不乏有思考.有亮点的精彩内容,推荐给同学们阅读学习. 山鸣谷应,相得益彰--杰对项目-第一阶段总结 该组对于可能 ...

  7. systemd服务的输出重定向到指定文件

    有一种更优雅的方法可以解决systemd输出到指定文件而非/var/log/message,需要使用systemd参数与rsyslog过滤器.并指示syslog过滤器按程序名称拆分其输出. syste ...

  8. [bug] Shell:paths must precede expression

    参考 https://www.cnblogs.com/peter1994/p/7297656.html

  9. [刷题] 447 Number of Boomerangs

    要求 给出平面上n个点,寻找存在多少点构成的三元组(i j k),使得 i j 两点的距离等于 i k 两点的距离 n 最多为500,所有点坐标范围在[-10000, 10000]之间 示例 [[0, ...

  10. Linux单用户模式(修改密码、运行级别)方法详解

    很多新手当面对"忘记 root 账户密码导致无法登陆系统"这个问题时,直接选择重新系统.其实大可不必,我只需要进入 emergency mode(单用户模式)更新 root 账户的 ...