【WPF】Silverlight中的Action与Trigger
最近做的Silverlight项目上用到了大量的拖拽,自动跟随等功能,由于赶时间,加上对Silverlight半生不熟,用的是最简单也是最不好维护的方法。项目忙完了闲下来,想重构一下代码,想起了Trigger和Action这两个东西,当初接触这两个东西不深,只是认识,不知道用。现在正好可以好好学习一下,参考了重多大神的代码之后,终于初步熟悉了它们。这里分享一下我对Trigger和Action的认识。
我用一个最简单的例子来说明Action与Trigger,点击一个Button弹出MessageBox。
建立一个Silverlight Application,引用System.Windows.Interactivity.dll程序集(这个程序集很重要,是使用Trigger,Action,Behavior必须引用的)。我们在MainPage里放一个Button并给一个Click事件。
xaml代码如下:
1: <UserControl x:Class="SilverlightApplication1.MainPage"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5: xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6: mc:Ignorable="d"
7: d:DesignHeight="300" d:DesignWidth="400">
8:
9: <Grid x:Name="LayoutRoot" Background="White">
10: <Button Content="Button" HorizontalAlignment="Left" Margin="35,31,0,0" Name="button1" VerticalAlignment="Top" Click="button1_Click" />
11: </Grid>
12: </UserControl>
cs代码如下:
1: public partial class MainPage : UserControl
2: {
3: public MainPage()
4: {
5: InitializeComponent();
6: }
7:
8: private void button1_Click(object sender, RoutedEventArgs e)
9: {
10: MessageBox.Show("Hello World!");
11: }
12: }
很简单,这是最传统的做法。
下面Action要上场了。所谓Action,就是去执行某些操作。可以根据需要创建自己的Action,常见的需要创建Action的情况有:改变属性、调用方法、打开窗口、导航到某个页面、设置焦点等。自定义Action可从 TriggerAction<DependencyObject>或TargetedTriggerAction<DependencyObject>继承,区别在于操作对象是关联对象还是特定的目标对象,实现时覆盖Invoke方法即可。我们新建一个简单的Action,代码如下:
1: public class Action1 : TriggerAction<DependencyObject>
2: {
3: public Action1()
4: {
5:
6: }
7:
8: protected override void Invoke(object o)
9: {
10: MessageBox.Show("Hello World! This message comes from an action.");
11: }
12: }
在Invoke方法里Show一个MessageBox。这样,一个Action这创建好了。如何使用它呢?看下面的代码。
xaml代码:
1: <UserControl x:Class="SilverlightApplication1.MainPage"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5: xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6: xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
7: xmlns:local="clr-namespace:SilverlightApplication1"
8: mc:Ignorable="d"
9: d:DesignHeight="300" d:DesignWidth="400">
10:
11: <Grid x:Name="LayoutRoot" Background="White">
12: <Button Content="Button" HorizontalAlignment="Left" Margin="35,31,0,0" Name="button1" VerticalAlignment="Top">
13: <i:Interaction.Triggers>
14: <i:EventTrigger EventName="Click">
15: <local:Action1 />
16: </i:EventTrigger>
17: </i:Interaction.Triggers>
18: </Button>
19: </Grid>
20: </UserControl>
运行结果如图:
很显然,Button的单击调用了那个Action,Button不再去触发xaml.cs里的那个事件处理方法了,而了触发了之前新建的Action1。回到xaml代码,EventTrigger是Silverlight自带的一个触发器(Trigger)。Trigger一量触发,就会执行对应的Action。这里我们把Action1与EventTrigger关联到一起(“关联”这个词可能用得不合适,反正就这个意思),EventTrigger触发Click事件,执行Action弹出MessageBox。而xaml.cs文件里的代码不再需要了。它的好处是不是已经看出来了?有效的分离了UI与后台代码。
下面Trigger正式登场。所谓Trigger,就是监听某些条件的变化,比如事件触发,属性值改变等,进而触发一些动作的发生。这些Triggers可能是EventTrigger、CollisionTrigger 等,当然更多的或许是创建自己的Trigger。自定义Trigger只需要从TriggerBase<DependencyObject>继承,并覆盖OnAttached和OnDetaching方法即可。我面来创建一个Trigger。代码如下:
1: public class Trigger1 : TriggerBase<Button>
2: {
3: protected override void OnAttached()
4: {
5: base.OnAttached();
6: this.AssociatedObject.Click += new RoutedEventHandler(Trigger1_Click);
7: }
8:
9: protected override void OnDetaching()
10: {
11: base.OnDetaching();
12: this.AssociatedObject.Click -= new RoutedEventHandler(Trigger1_Click);
13: }
14:
15: protected void Trigger1_Click(object sender, RoutedEventArgs e)
16: {
17: MessageBox.Show("Hello World! This message comes from a trigger.");
18: }
19: }
代码中我们用到了AssociationObject这个属性,这个属性表示绑定Trigger的对象,这里是一个Button,OnAttached中注册一个Click事件处理方法,OnDetching中取消注册(如果不取消注册,当这个Button上其它触发器触发时,这个触发器的效果还会重现,因为Click触发之后委托链上所有注册方法都会执行, 具体情况具体分析是否需要取消注册)。
在Xaml中这样来使用这个Trigger:
1: <Grid x:Name="LayoutRoot" Background="White">
2: <Button Content="Button" HorizontalAlignment="Left" Margin="35,31,0,0" Name="button1" VerticalAlignment="Top">
3: <i:Interaction.Triggers>
4: <local:Trigger1 />
5: </i:Interaction.Triggers>
6: </Button>
7: </Grid>
运行如果如下:
这里Trigger1被触发了。
其实,触发器(Trigger)和动作(Action)是协同工作的。当某事件发生的时候,Trigger就会触发并调用一个Action,Trigger和Action组成了最简单的行为(Behavior下次再讨论)表现形式。
最后,我们让Trigger1和Action1协同工作一下。Trigger1的代码改一改:
1: public class Trigger1 : TriggerBase<Button>
2: {
3: protected override void OnAttached()
4: {
5: base.OnAttached();
6: this.AssociatedObject.Click += new RoutedEventHandler(Trigger1_Click);
7: }
8:
9: protected override void OnDetaching()
10: {
11: base.OnDetaching();
12: this.AssociatedObject.Click -= new RoutedEventHandler(Trigger1_Click);
13: }
14:
15: protected void Trigger1_Click(object sender, RoutedEventArgs e)
16: {
17: InvokeActions(null);
18: }
19: }
Trigger1_Click方法里调用InvokeActions来执行“关联”到这个Trigger上的Action。Xaml如下:
1: <Grid x:Name="LayoutRoot" Background="White">
2: <Button Content="Button" HorizontalAlignment="Left" Margin="35,31,0,0" Name="button1" VerticalAlignment="Top">
3: <i:Interaction.Triggers>
4: <local:Trigger1>
5: <local:Action1 />
6: </local:Trigger1>
7: </i:Interaction.Triggers>
8: </Button>
9: </Grid>
运行结果如下:
这里,Button绑定了Trigger1,Attach这个Trigger1时把Click事件注册上(OnAttached方法。关于Attach,请参考“附加属性”),所以单击Button就调用了绑定在Trigger1上的Action1。
至于这两个东西的好处就不必多说了,分离了UI与代码,提高了代码的复用。
好了,初学Trigger和Action,大致缕了一下它们之间的关系,就简单介绍到这,欢迎一起讨论。更神奇的Behavior将在下篇中介绍。
附上上面的源代码
【WPF】Silverlight中的Action与Trigger的更多相关文章
- WPF/Silverlight中图形的平移,缩放,旋转,倾斜变换演示
原文:WPF/Silverlight中图形的平移,缩放,旋转,倾斜变换演示 为方便描述, 这里仅以正方形来做演示, 其他图形从略. 运行时效果图:XAML代码:// Transform.XAML< ...
- WPF/Silverlight中的RichTextBox总结
WPF/Silverlight中的RichTextBox总结 在WPF或者是在Silverlight中有个非常强大的可以编辑的容器控件RichTextBox,有的时间会采取该控件来作为编辑控件.鉴 ...
- WPF,SilverLight中直线的样式示例
原文:WPF,SilverLight中直线的样式示例 XAML代码:// LineStyle.xaml<Viewbox Width="600" Height="50 ...
- WPF/Silverlight Template使用及总结(转)
WPF/Silverlight 中的控件都有Style和Template两种属性.前者解释为样式,是用来改变控件原有属性的,比如 Button 控件的(Width,Height,Background ...
- WPF/Silverlight深度解决方案:(一)解锁被Storyboard束缚的关联属性
原文 WPF/Silverlight深度解决方案:(一)解锁被Storyboard束缚的关联属性 如果您在使用WPF/Silverlight进行相关动画开发中使用了Storyboard,并对关联属性进 ...
- WPF/Silverlight深度解决方案:(七)HLSL自定义渲染特效之完美攻略(中)
原文:WPF/Silverlight深度解决方案:(七)HLSL自定义渲染特效之完美攻略(中) 通过上一节的解说,大家是否已经对HLSL有了较深刻的认识和理解,HLSL的渲染不仅仅局限于静态处理,通过 ...
- WPF基础到企业应用系列7——深入剖析依赖属性(WPF/Silverlight核心)
一. 摘要 首先圣殿骑士非常高兴这个系列能得到大家的关注和支持.这个系列从七月份開始到如今才第七篇,上一篇公布是在8月2日,掐指一算有二十多天没有继续更新了,最主要原因一来是想把它写好,二来是由于近期 ...
- 三、Silverlight中使用MVVM(三)——进阶
这篇主要引申出Command结合MVVM模式在应用程序中的使用 我们要做出的效果是这样的 就是提供了一个简单的查询功能将结果绑定到DataGrid中,在前面的基础上,这个部分相对比较容易实现了 我们在 ...
- 浅谈WPF本质中的数据和行为
WPF缩写为Windows Presentation Foundation的缩写,本文所要谈的就是WPF本质中的数据和行为,希望通过本文能对大家了解WPF本质有所帮助. 如果自己来做一个UI框架,我们 ...
随机推荐
- Cygwin、MinG、MSys区别与联系(转)
转自:https://www.biaodianfu.com/cygwin-ming-msys.html 什么是Cygwin? Cygwin,原Cygnus出品(已被红帽收购),目前是RedHat名下的 ...
- FJUT 毒瘤3(二分 + 最大匹配)题解
毒瘤3 TimeLimit:1000MS MemoryLimit:256MB 64-bit integer IO format:%lld Problem Description 字节跳动有n款产 ...
- POJ 2400 Supervisor, Supervisee(KM二分图最大权值匹配)题解
题意:n个老板n个员工,先给你n*n的数据,i行j列代表第i个老板第j喜欢的员工是谁,再给你n*n的数据,i行j列代表第i个员工第j喜欢的老板是谁,如果匹配到第k喜欢的人就会产生一个分数k-1.现在让 ...
- (转)MongoDB学习
(二期)25.分布式文件存储数据库MongoDB [课程25]mongod...命令.xmind96.9KB [课程25]MongoD...概念.xmind0.5MB [课程25]MongoDB简介. ...
- 今天的任务--git练习
克隆远程仓库项目 从版本控制中选择git 填写地址和本地目录,test测试成功后点击clone 克隆完成回到主界面,点击open打开刚才克隆的项目 git操作 添加文件py1.html 打开命令行 新 ...
- spring与mybatis四种整合方法
转载: 1.采用数据映射器(MapperFactoryBean)的方式,不用写mybatis映射文件,采用注解方式提供相应的sql语句和输入参数. (1)Spring配置文件: <!-- 引 ...
- 如何在 sublime text 中以当前文件目录打开 cmd
需求描述 sublime 固定可以自己设置和添加新的编译环境,比如在我们写 js 的时候可能会添加 node 来对 js 文件进行运行.但是,这样做的结果是,我们只能看到运行结果.有时候还希望能做些其 ...
- -第1章 HTMLCSS方法实现下拉菜单
中英文的自动换行问题 把下面代码中的 javascript 改成 子菜单1 试试, 如果英文的话宽度会自动撑开, 用中文不会, 而直接转行下来. <ul> <li><a ...
- 针对list集合进行分页展示
直接定义个工具类,代码如下: package com.jk51.modules.wechat.web.util; import java.util.Collections; import java.u ...
- Select2 添加默认值
折腾很久才解决问题 $.ajax({ url: '@Url.Action("GetSystemSzzdItem", "CangpinGushi")', type ...