深入理解MVVM模式中Silverlight的Trigger、Action和Behavior及Silverlight的继承机制
接触Silverlight已经有两三个月了,开始一直感觉他和Winform很相似,拖拖控件就行了,所以一直把经历放在了研究后台和服务器交互和性能优化上面,很少去仔细研究Silverlight的页面。前几天,公司突然让修改一个Winform的项目,再回过头来看Winform,有种"不堪回首"的感觉。
十一长假即将来临,在这里先祝大家假期快乐。今天难得有空,抽出点时间研究了一下Silverlight的继承和触发器,拿出来和大家分享一下。Silverlight和WPF中页面布局使用的都是XAML,颇为相似,学习WPF的也可以参考一下。
一、Silverlight中的继承
那么先来说一下Silverlight中的继承吧,我们经常在后台代码中使用继承,实现代码的重用。那么在前端页面是否可以使用继承,实现代码和控件的重用呢?答案是可以的。通过学习继承,我们可以更深入的理解XAML。下面来写一个Demo,一起来看一下,首先新建一个Silverlight项目,名字就叫SLDemo吧,添加默认的网站,建完项目后目录如下:

既然要说继承,那么首先要有个父类,新加一个Class,名字就叫BaseView,添加一些属性,代码如下:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes; namespace SLDemo
{
public class BaseView : UserControl
{
public string Title { get; set; }
public int WinWidth { get; set; }
public int WinHeight { get; set; }
}
}
这里简单添加一些属性,我们看到所有的页面控件都继承自UserControl,所以我们这个父类也要继承UserControl,然后修改MainPage代码,来继承我们这个类。
这里要注意的是,Silverlight里面页面和后台cs文件要继承自同一个父类,所以前端和后台都要改,后台cs文件很简单,修改后代码如下:
namespace SLDemo
{
public partial class MainPage : BaseView
{
public MainPage()
{
InitializeComponent();
}
}
}
只是把父类UserControl改成BaseView即可,然后来看前端页面的修改方法:
<sld:BaseView x:Class="SLDemo.MainPage"
xmlns:sld="clr-namespace:SLDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="600"> <Grid x:Name="LayoutRoot" Background="White"> </Grid>
</sld:BaseView>
来看一下代码变成什么样了?是不是和之前大不一样了,<Usercontrol></Usercontrol>没有了?是不是有种"高大尚"的感觉,瞬间感觉让人看不懂了?下面我来解释一下:
注意看第二行,我们引入了一个命名空间,XAML中引入命名空间就是
xmlns:{前缀}="clr-namespace:{命名空间}"
这里我们把前缀写成了sld(SLDemo的前三个字母),然后把Usercontrol改成我们的BaseView,和后台cs文件统一。实际上,XAML中应该这样写:
<命名空间:类名></命名空间:类名>
但是由于Usercontrol是系统默认的,所以前面的命名空间就省了。接下来,先拖几个控件上去看看,会发生什么,这里拖一个TabControl和一个Button吧,代码如下:
<sld:BaseView x:Class="SLDemo.MainPage"
xmlns:sld="clr-namespace:SLDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="600"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"> <Grid x:Name="LayoutRoot" Background="White">
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="308,119,0,0" Name="button1" VerticalAlignment="Top" Width="75" />
<sdk:TabControl Height="100" HorizontalAlignment="Left" Margin="210,205,0,0" Name="tabControl1" VerticalAlignment="Top" Width="200" />
</Grid>
</sld:BaseView>
可以看到,Button和之前一样,tabcontrol和之前还是一样(都要引用命名空间),这里主要说一下命名空间,可以看到上面多了一行代码:
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
这里引入TabControl的命名空间,看我标红的,然后用这个前缀去添加Tabcontrol,所以以后我们引用自己的自定义控件也是这样,先引用命名控件,然后通过前缀来访问。
当然,写了这么多,我们还是再写一个控件,其实Silverlight中Page大多用来显示控件,页面都是由控件堆出来的,然后在窗体显示时,设置他的Content属性来呈现。
到这里,大家就可以通过继承来重写和扩展控件了。(今天先说到这里,以后会详细介绍开发自定义控件)。
二、Silverlight的Trigger、Action和Behavior
现在比较流行用MVVM来开发Silverlight项目,目的是实现XAML和代码的分离。今天就来说一下Trigger、Action和Behavior.
首先来说一下三者的关系:
Trigger : 触发器,就像他的名字一样,是用来监听事件,然后执行某段代码
Action: 动作,就是执行一段代码
Behavior: 行为,看起来好像不太好理解,其实他可以看作是Trigger和Action的组合
首先来说一下Trigger和Action吧,首先来写一个Action,新建一个类MyAction,在写代码之前,我们要先引入一个命名空间,如图:

然后在代码中引用命名空间System.Windows.Interactivity;继承TriggerAction类,代码如下:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Interactivity; namespace SLDemo
{
public class MyAction : TriggerAction<DependencyObject>
{
protected override void Invoke(object parameter)
{
MessageBox.Show("你触发了一个Action!");
}
}
}
这里我们重写了Invoke方法,让他弹出一条消息。下面我们来使用这个Action,让他来响应一个事件,修改XAML代码如下:
<sld:BaseView x:Class="SLDemo.MainPage"
xmlns:sld="clr-namespace:SLDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="600"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"> <Grid x:Name="LayoutRoot" Background="White">
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="308,119,0,0" Name="button1" VerticalAlignment="Top" Width="75">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<sld:MyAction />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button> </Grid>
</sld:BaseView>
这里我们给一个按钮添加了一个Trigger来侦听单击事件,然后绑定MyAction,运行后我们单击按钮,会弹出消息框。
下面,我们来给Action传递一个参数,当然你可以多加几个,我们就传递一个BtnName属性吧,修改MyAction代码如下:
namespace SLDemo
{
public class MyAction : TriggerAction<DependencyObject>
{
public string BtnName { get; set; }
protected override void Invoke(object parameter)
{
MessageBox.Show("你触发了一个Action!按钮名称是:" + this.BtnName);
}
}
}
我们只是添加了一个属性,下面来看看如何使用:

运行效果如下:

我们就像平常写XAML那样,写一个属性就可以传递一个参数到Action里面,当然这里也可以绑定一个变量。但是实际开发中,我们不需要这样做,因为我们把变量写在ViewModel中,写Action可以给一些Combox绑定SelectedChanged事件,目的还是实现布局和代码分离。
Behavior
下面来看一下神奇的Behavior吧,有了Behavior,可以实现一些特效的重复使用,下面来写一个简单的例子看一下,就写一个关于Textbox的吧,新建一个类,名字叫做TextboxBehavior,代码如下:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Interactivity; namespace SLDemo
{
public class TextboxBehavior : Behavior<TextBox>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.TextChanged += new TextChangedEventHandler(AssociatedObject_TextChanged);
} void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e)
{
if (AssociatedObject.Text.Length < )
{
AssociatedObject.Foreground = new SolidColorBrush(Color.FromArgb(, , , ));
}
else
{
AssociatedObject.Foreground = new SolidColorBrush(Color.FromArgb(, , , ));
}
}
}
}
然后在XAML中添加如下代码:

这个时候,Textbox就绑定了我们的TextboxBehavior了,运行看下效果:

当输入的内容小于六个字符的时候,显示红色

大于等于六个字符时就变成绿色。
我们一旦写好了这个Behavior,所有页面的Textbook都可以使用,是不是感觉很强大!源码已经上传,在下面下载。
深入理解MVVM模式中Silverlight的Trigger、Action和Behavior及Silverlight的继承机制的更多相关文章
- silverlighter下MVVM模式中利用Behavior和TargetedTriggerAction实现文本框的一些特效
在silverlight一般开发模式中,给文本框添加一些事件是轻而易举的,然而MVVM开发模式中,想要给文本框添加一些事件并非那么容易,因为MVVM模式中,只有ICommand接口,而且也只有Butt ...
- Messenger在MVVM模式中的应用
Messenger在MVVM模式中的应用 Messenger在MVVM中应用的前提 我们知道在MVVM架构中,系统平台的Silverlight客户端界面开发和业务逻辑已经被分开,XAML是SL的主要部 ...
- WPF ContextMenu 在MVVM模式中绑定 Command及使用CommandParameter传参
原文:WPF ContextMenu 在MVVM模式中绑定 Command及使用CommandParameter传参 ContextMenu无论定义在.cs或.xaml文件中,都不继承父级的DataC ...
- 在MVVM模式中,按钮Click事件的绑定方法
在MVVM模式中,我们将Button的方法写到ViewModel中,然后绑定到前端界面.通常的做法是写一个类,继承ICommand接口,然而如果按钮比较多的话,就需要写很多的类,对于后期维护造成很大的 ...
- “Win10 UAP 开发系列”之 在MVVM模式中控制ListView滚动位置
这个扩展属性从WP8.1就开始用了,主要是为了解决MVVM模式中无法直接控制ListView滚动位置的问题.比如在VM中刷新了数据,需要将View中的ListView滚动到顶部,ListView只有一 ...
- WPF MVVM模式中,通过命令实现窗体拖动、跳转以及显隐控制
原文:WPF MVVM模式中,通过命令实现窗体拖动.跳转以及显隐控制 在WPF中使用MVVM模式,可以让我们的程序实现界面与功能的分离,方便开发,易于维护.但是,很多初学者会在使用MVVM的过程中遇到 ...
- MVVM模式中WPF数据的完全绑定
一:截图,描述:将后台代码的姓名.年龄绑定到文本框,单击”增加年龄“--年龄自+1,单击”显示年龄“--弹出年龄的显示对话框,实现了从文本框修改年龄和后台更改年龄并显示到文本框 运行结果和解决方案管理 ...
- MVVM模式中ViewModel和View、Model有什么区别
Model:很简单,就是业务逻辑相关的数据对象,通常从数据库映射而来,我们可以说是与数据库对应的model. View:也很简单,就是展现出来的用户界面. 基本上,绝大多数软件所做的工作无非就是从数据 ...
- 理解MVVM模式
1.WPF的核心是数据绑定. 2.考虑这样一个场景:界面上有一个TextBox显示Person的年龄,一个Button,点击一次Button,年龄加1. 3.做一个View,上面有TextBox和Bu ...
随机推荐
- extjs学习(关于grid)
1.想要调整某一列在表格中的顺序,可以使用mapping(索引是从0开始的) var store = new Ext.data.ArrayStore({ data:data, fields:[ {na ...
- Python 3.5 连接Mysql数据库(pymysql 方式)
由于 MySQLdb 模块还不支持 Python3.x,官方的Mysql连接包只支持到3.4,所以 Python3.5 如果想连接MySQL需要安装 pymysql 模块. pymysql 模块可以通 ...
- 121. Best Time to Buy and Sell Stock (一) leetcode解题笔记
121. Best Time to Buy and Sell Stock Say you have an array for which the ith element is the price of ...
- ORACLE RAC 11G 更改 /etc/hosts文件
来自官方文档:()Can I change the public hostname in my Oracle Database 10g Cluster using Oracle Clusterware ...
- 【jquery】flexiGrid新增功能的方式
到目前为止,我用过的jquery表格插件只有jqGrid和flexiGrid.今天,只说后者. 关于参数配置,使用方法,博客园文章很多. 原生的flexiGrid架包不大,内容可以扩展,比如在每行数据 ...
- jsp实现回车登录
<body onkeydown="if(event.keyCode==13){login()}"> 内容0...... </body> 注:body里面加上 ...
- Swift基础语法(五)枚举、结构体与类的区别
swift中的结构体值可以是整型.浮点型.字符串.字符.元祖,如果不赋值默认为整型且从0开始计数,如果为整型枚举且要求不是从0开始只需指定枚举的第一个值以后的值自动依次加1 引用方式也与oc有所出入 ...
- 在 Mac OS 上创建并运行 ASP.NET Core 1.0 网站
var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...
- 使用git svn clone迁移svn仓库
使用git svn clone迁移svn仓库 clone命令可以指定很多参数,主要用到这些,你也可以使用git svn help查看完整的参数列表. git svn clone https://172 ...
- 最小和(min)
题目描述: N 个数排成一排,你可以任意选择连续的若干个数,算出它们的和.问该如何选择才能 使得和的绝对值最小. 如:N=8 时,8个数如下: 1 2 3 4 5 6 ...