WPF 后台代码做 TranslateTransform 的动画
本文告诉大家,在后台代码,对 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 的属性做动画将会失效。好在官方文档里面有说到这点
可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 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 的动画的更多相关文章
- 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 ...
- WPF后台代码实现TextBlock滚动条
方法一: 常规的WPF操作: <ScrollViewer Width=" VerticalScrollBarVisibility="Auto" Horizontal ...
- C# Wpf 后台代码设定UIElement的Canvas位置属性值
后台in-code设定元件UIElement的Canvas位置属性的两种方法: 1.UIElement.SetValue()方法 uiElement.SetValue(Canvas.TopProper ...
- 7.7 WPF后台代码绑定如果是属性,必须指定一下数据上下文才能实现,而函数(click)就不用
如: private bool _IsExportWithImage; /// <summary> /// 是否选择导出曲线图 /// </summary> public bo ...
- WPF MVVM 架构 Step By Step(4)(添加bindings - 完全去掉后台代码)
之前的改进已经挺棒的,但是我们现在知道了后台代码的问题,那是否可能把后台代码全部去除呢?这时候就该WPF binding 和 commands 来做的事情了. WPF就是以超吊的binding,com ...
- WPF后台动画DoubleAnimation讲解
WPF后台动画,使用DoubleAnimation做的. 1.移动动画 需要参数(目标点离最上边的位置,目标点离最左边的位置,元素名称) Image mImage = new Image(); Flo ...
- WPF内嵌代码和后台代码简单混合使用
下面实例展示了WPF内嵌代码和后台代码混合使用,一个简单基础的实例: xaml文件: <Window x:Class="WPF内嵌代码和后台代码混合使用.MainWindow" ...
- WPF MVVM 架构 Step By Step(3)(把后台代码移到一个类中)
我觉得大部分开发者应该已经知道怎么去解决这个问题.一般都是把后台代码(GLUE code)移动到一个类库.这个类库用来代表UI的属性和行为.任何代码当被移到一个类库中时都可以被编译成一个DLL,然后可 ...
- wpf 分别用 xaml 和后台代码实现 色彩渐变
xaml 方法: <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.micros ...
随机推荐
- Android拆分与加载Dex的多种方案对比
http://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=207151651&idx=1&sn=9eab282711f4eb2b ...
- 迷失在Mysql的锁世界~
1.饮料 这是一杯饮料. 这是3杯饮料,每杯饮料的味道各不相同. 但是人类并不称呼[饮料]为[饮料],而是称呼[饮料]为[记录]. 2.红章鱼 这个红色的,长的像章鱼的家伙,我们就叫它红章鱼~ 红章鱼 ...
- memcache 和 redis 的区别
1)Redis中,并不是所有的数据都一直存储在内存中的,这是和Memcache相比一个最大的区别.2)Redis在很多方面具备数据库的特征,或者说就是一个数据库系统,而Memcache只是简单的K/V ...
- [bug]MySQL [Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause
参考 http://www.10qianwan.com/articledetail/220315.html
- 一文搞懂:java中的VO、PO、BO、DAO、POJO
针对java工程里的各种带O的对象,进行分析,了解各自的作用. PO:persistent object,持久对象.与数据库里表字段一一对应.PO是一些属性,以及set和get方法组成.一般情况下,一 ...
- CentOS 7 设置日期和时间 timedatectl
CentOS 7 设置日期和时间 在CentOS 6版本,时间设置有date.hwclock命令,从CentOS 7开始,使用了一个新的命令timedatectl. timedatectl [root ...
- Ansible命令行方式执行
Ansible ad-hoc 什么是ad-hoc? 临时命令,执行完不会保存,类似于批量执行命令. ansible的选项 -i # 指定主机清单 ansible rsync -m ping -i 1. ...
- mysql示例及练习2
#创建数据库并应用create database shopdb;use shopdb;#创建表customerscreate table customers(c_id int primary key ...
- mysql基础之mariadb galera集群(多主)
一.概念 galera集群多用于关键性业务,因为galera集群为了数据的一致性,采用的是同步的机制,这就使galera牺牲了一部分性能来换取数据一致性. galera集群是基于wsrep协议(端口4 ...
- pre -regulator 前端稳压器
regulator