当前位置: 首页 > news >正文

WPF自定义控件 《动画》

通常,当WPF常用的控件不能满足我们的需求时,我们就会创建自己的控件,有用户控件和自定义控件两种。就很想winform中的,用户控件可以基于当前的控件组合成我们需要的控件,而自定义控件那么就是从0做起,不过继承自一个和我们功能相似的类会效果更好,比如CustomControl继承Button的一些方法特性。

UserControl非常好理解,网上有许多教程。

CustomControl由于其没有Xaml界面,界面是放到Themes/Generic.xaml中来定义的,所以在开发中,特别是初学者带来一些困惑,今天怒搞一天,把自己的经验分享一下,也希望前辈们能多多指教。

好,创建一个CustomControl,发现目录机构如下

我们并没有看到CustomControl.xaml文件,打开CustomControl1.cs,代码如下

static TemControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(TemControl), new FrameworkPropertyMetadata(typeof(TemControl)));
        }

 

其实,这里就是为我们的控件指定了一个默认的外观,这个外观在Themes/Generic.xaml里面,这是整个资源文件的代码

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TemControl">
    <Style TargetType="{x:Type local:TemControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:TemControl}">
                    <ControlTemplate.Resources>
                        <Storyboard x:Key="Alarm">
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="background">
                                <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                                <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                    </ControlTemplate.Resources>
                    <!--<ControlTemplate.Triggers>
                        <EventTrigger RoutedEvent="UIElement.MouseLeftButtonDown" SourceName="background">
                            <BeginStoryboard Storyboard="{StaticResource Alarm}"/>
                        </EventTrigger>
                    </ControlTemplate.Triggers>-->
                    <Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="Tempreature" Width="250" Height="280" Clip="F1 M 0,0L 250,0L 250,280L 0,280L 0,0">
                        <Canvas x:Name="background" Width="250" Height="280" Canvas.Left="0" Canvas.Top="0" RenderTransformOrigin="0.5,0.5">
                            <Canvas.RenderTransform>
                                <TransformGroup>
                                    <ScaleTransform/>
                                    <SkewTransform/>
                                    <RotateTransform/>
                                    <TranslateTransform/>
                                </TransformGroup>
                            </Canvas.RenderTransform>
                            <Path x:Name="Path" Width="230" Height="230" Canvas.Left="10" Canvas.Top="4.99991" Stretch="Fill" Data="F1 M 20,4.99991L 230,4.99991C 235.523,4.99991 240,9.47702 240,14.9999L 240,225C 240,230.523 235.523,235 230,235L 20,235C 14.4772,235 10,230.523 10,225L 10,14.9999C 10,9.47702 14.4772,4.99991 20,4.99991 Z ">
                                <Path.Fill>
                                    <LinearGradientBrush StartPoint="0.5,1.25168" EndPoint="0.5,-0.25168">
                                        <LinearGradientBrush.GradientStops>
                                            <GradientStop Color="#FF000000" Offset="0"/>
                                            <GradientStop Color="#FF4C4E4C" Offset="0.748837"/>
                                            <GradientStop Color="#FF989D98" Offset="1"/>
                                        </LinearGradientBrush.GradientStops>
                                    </LinearGradientBrush>
                                </Path.Fill>
                                <Path.Effect>
                                    <DropShadowEffect BlurRadius="8" ShadowDepth="3.77953" Opacity="0.599998" Color="#FF000000" Direction="315"/>
                                </Path.Effect>
                            </Path>
                        </Canvas>
                        <Canvas x:Name="tempreature" Width="250" Height="280" Canvas.Left="0" Canvas.Top="0">
                            <Viewbox x:Name="Group" Width="58" Height="191" Canvas.Left="45" Canvas.Top="25">
                                <Canvas Width="58" Height="191">
                                    <Path x:Name="Path_0" Width="20" Height="147" Canvas.Left="16.115" Canvas.Top="1.34552" Stretch="Fill" StrokeThickness="6" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Stroke="#FF96C240" Fill="#0096C240" Data="F1 M 26.115,4.34552L 26.115,4.34552C 29.981,4.34552 33.115,7.47954 33.115,11.3455L 33.115,138.345C 33.115,142.211 29.981,145.345 26.115,145.345L 26.115,145.345C 22.249,145.345 19.115,142.211 19.115,138.345L 19.115,11.3455C 19.115,7.47954 22.249,4.34552 26.115,4.34552 Z ">
                                        <Path.Effect>
                                            <DropShadowEffect BlurRadius="8" ShadowDepth="3.77953" Opacity="0.599998" Color="#FF000000" Direction="315"/>
                                        </Path.Effect>
                                    </Path>
                                    <Ellipse x:Name="Ellipse" Width="49.6471" Height="46.8889" Canvas.Left="1.29151" Canvas.Top="136.303" Stretch="Fill" Fill="#FF96C240">
                                        <Ellipse.Effect>
                                            <DropShadowEffect BlurRadius="8" ShadowDepth="3.77953" Opacity="0.599998" Color="#FF000000" Direction="315"/>
                                        </Ellipse.Effect>
                                    </Ellipse>
                                </Canvas>
                            </Viewbox>
                        </Canvas>
                    </Canvas>

                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

 

我们只需要关注ControTemplate这一标记,内部其实就是实现我们自定义控件的外观。好,进入正题,今天之所以研究一天是因为对于它的动画故事版。

故事版我们可以在Blend中设计,然后移植到这里即可,但是需要注意的是:Resouce和Trigger都应该放到ControlTemplate下,而不是Style下。

有时某些动画的控制我需要在后台控制。那就是只需要获取到故事版,然后在相应的事件上让故事版播放即可。

那么如何获取放在Themes/Generic.xaml下的故事版呢?

查阅MSDN,要访问ControlTemplate下的资源,可以使用Template.Resources属性获得资源字典,得到资源字典后,那就是根据Key值获取到相应的资源了。这里需要注意,要获得资源字典

必须重写父类的OnApplyTemplate方法,从中不只能得到资源,也能得到ControlTemplate下的控件。

public override void OnApplyTemplate()
        {
            ResourceDictionary r = this.Template.Resources;
            sb = r["Alarm"] as Storyboard;
            ca = this.GetTemplateChild("background") as Canvas;
            base.OnApplyTemplate();
        }

 

好,得到故事版了,那么在重写单击事件,然后让故事版播放,发现出错了

看我们故事版的代码

<Storyboard x:Key="Alarm">
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="background">
                                <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                                <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>

 

其中Storyboard.TargetName="background"这一段出错,至于为何报错,为何不能查找到,还请前辈们告之,这里我找到了解决办法。

参看http://social.msdn.microsoft.com/Forums/zh-TW/802/thread/1365449e-965d-4df7-82df-e3e0e8d0ca19

那么我们需要为故事版的Begin方法将Target对象传进去。background是Canvas对象,前面提到使用GetTemplateChild很容易获取到ControlTemplate下的控件。

获取到background后,带入Begin方法,功能实现。

public override void OnApplyTemplate()
        {
            ResourceDictionary r = this.Template.Resources;
            sb = r["Alarm"] as Storyboard;
            ca = this.GetTemplateChild("background") as Canvas;
            base.OnApplyTemplate();
        }

        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            sb.Begin(ca);
            base.OnMouseLeftButtonDown(e);
        }

 

这样,就通过后台控制到了动画的播放。

转载于:https://www.cnblogs.com/HelloMyWorld/archive/2013/04/03/2998660.html

相关文章:

  • Java classLoader【转】
  • linux系统时间修改及同步
  • ISP采用的 ISIS链接状态路由协议
  • Spring Aop的另类问题
  • vs2010创建Web Service程序
  • 宋体、文件-Ubuntu Linux中配置adb-by小雨
  • 测试数据整数搜索——Ny 90 整数划分
  • 类的静态成员
  • GE打造工业互联网
  • 如何让JTable的内容显示 居中
  • 最大堆、最小堆操作-删除、
  • 日期条件SQL 截取日期作为条件
  • 《Head First设计模式》 读书笔记10 迭代器与组合模式 The Iterator and Composite Patterns...
  • CodeLobster PHP Edition v4.5.3 Professional 注册码
  • js ol.ui.alternation
  • ES6指北【2】—— 箭头函数
  • [NodeJS] 关于Buffer
  • Invalidate和postInvalidate的区别
  • laravel with 查询列表限制条数
  • Redis 懒删除(lazy free)简史
  • Shell编程
  • SpiderData 2019年2月16日 DApp数据排行榜
  • spring + angular 实现导出excel
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • Web Storage相关
  • 百度地图API标注+时间轴组件
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 工程优化暨babel升级小记
  • 猫头鹰的深夜翻译:Java 2D Graphics, 简单的仿射变换
  • 强力优化Rancher k8s中国区的使用体验
  • 使用putty远程连接linux
  • 跳前端坑前,先看看这个!!
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • [Shell 脚本] 备份网站文件至OSS服务(纯shell脚本无sdk) ...
  • Mac 上flink的安装与启动
  • puppet连载22:define用法
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (LeetCode 49)Anagrams
  • (NSDate) 时间 (time )比较
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (附源码)基于SpringBoot和Vue的厨到家服务平台的设计与实现 毕业设计 063133
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (一)VirtualBox安装增强功能
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .net core Swagger 过滤部分Api
  • .NET Framework与.NET Framework SDK有什么不同?
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?
  • .NET(C#、VB)APP开发——Smobiler平台控件介绍:Bluetooth组件
  • .Net下使用 Geb.Video.FFMPEG 操作视频文件
  • .net之微信企业号开发(一) 所使用的环境与工具以及准备工作