利刃 MVVMLight 6:命令基础

在MVVM Light框架中,事件是WPF应用程序中UI与后台代码进行交互的最主要方式,与传统方式不同,mvvm中主要通过绑定到命令来进行事件的处理,

因此要了解mvvm中处理事件的方式,就必须先熟悉命令的工作原理。

RelayCommand命令:
    WPF命令是通过实现 ICommand 接口创建的。 ICommand 公开了两个方法(Execute 及 CanExecute)和一个事件(CanExecuteChanged)。

Execute方法 执行与命令关联的操作
CanExecute方法  确定是否可以在当前命令目标上执行命令,返回值为true则按钮可用,为false的时候按钮disable。在MvvmLight中实现ICommand接口的类是RelayCommand

RelayCommand通过构造函数初始化Execute 和 CanExecute方法,因此,构造函数传入的是委托类型的参数,

Execute 和 CanExecute则执行的是委托的方法。如图:

相对于CodeBehind 的方式,使用命令会好很多:

最大的特点就是解耦View和ViewModel的行为交互,将视图的显示和业务逻辑分开。对View上的某个元素进行命令的绑定,触发点击操作的时候,这个按钮实际完成
的是对应ViewModel中的所绑定的方法的执行。这里我们用到Mvvm框架中的RelayCommand。

现在我们来看一个例子,将我们上篇的那个例子改装一下,加进CanExcute()方法和列表数据的呈现。

Model代码:

 1  [MetadataType(typeof(BindDataAnnotationsViewModel))]
 2     public class ValidateUserInfo:ValidateModelBase
 3     {
 4         #region 属性
 5         private String userName;
 6         /// <summary>
 7         /// 用户名
 8         /// </summary>
 9         [Required]
10         public String UserName
11         {
12             get { return userName; }
13             set { userName = value; RaisePropertyChanged(() => UserName); }
14         }
15
16
17
18         private String userPhone;
19         /// <summary>
20         /// 用户电话
21         /// </summary>
22         [Required]
23         [RegularExpression(@"^[-]?[1-9]{8,11}\d*$|^[0]{1}$", ErrorMessage = "用户电话必须为8-11位的数值.")]
24         public String UserPhone
25         {
26             get { return userPhone; }
27             set { userPhone = value; RaisePropertyChanged(() => UserPhone); }
28         }
29
30
31
32         private String userEmail;
33         /// <summary>
34         /// 用户邮件
35         /// </summary>
36         [Required]
37         [StringLength(100, MinimumLength = 2)]
38         [RegularExpression("^\\s*([A-Za-z0-9_-]+(\\.\\w+)*@(\\w+\\.)+\\w{2,5})\\s*$", ErrorMessage = "请填写正确的邮箱地址.")]
39         public String UserEmail
40         {
41             get { return userEmail; }
42             set { userEmail = value; RaisePropertyChanged(() => UserEmail);  }
43         }
44         #endregion

View代码:

提交按钮绑定了一个Command,这个Command指向对用的ViewModel中的SubmitCmd 方法。这样确实很赞,SubmitCmd 独立性、复用性很高。

 1 <Window x:Class="MVVMLightDemo.View.CommandView"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         DataContext="{Binding Source={StaticResource Locator},Path=Command}"
 5         Title="CommandView" Height="500" Width="800">
 6     <Grid>
 7         <StackPanel Orientation="Vertical" >
 8             <GroupBox Header="命令" Margin="10 20 10 10" >
 9                 <StackPanel Orientation="Vertical" Margin="0,10,0,0">
10                     <StackPanel.Resources>
11                         <Style TargetType="StackPanel">
12                             <Setter Property="Orientation" Value="Horizontal" />
13                             <Setter Property="Margin" Value="0,0,0,4" />
14                         </Style>
15                         <Style TargetType="Label" BasedOn="{StaticResource {x:Type Label}}">
16                             <Setter Property="Width" Value="100" />
17                             <Setter Property="VerticalAlignment" Value="Center" />
18                         </Style>
19                         <Style TargetType="CheckBox" BasedOn="{StaticResource {x:Type CheckBox}}">
20                             <Setter Property="Padding" Value="0,3" />
21                         </Style>
22                         <Style TargetType="RadioButton" BasedOn="{StaticResource {x:Type RadioButton}}">
23                             <Setter Property="Padding" Value="0,3" />
24                         </Style>
25                     </StackPanel.Resources>
26
27                     <StackPanel>
28                         <Label Content="用户名" Target="{Binding ElementName=UserName}"/>
29                         <TextBox Width="150"
30                                  Text="{Binding ValidateUI.UserName,UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}" >
31                         </TextBox>
32                     </StackPanel>
33                     <StackPanel>
34                         <Label Content="用户邮箱" Target="{Binding ElementName=UserEmail}"/>
35                         <TextBox Width="150" Text="{Binding ValidateUI.UserEmail, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
36                     </StackPanel>
37                     <StackPanel>
38                         <Label Content="用户电话" Target="{Binding ElementName=UserPhone}"/>
39                         <TextBox Width="150" Text="{Binding ValidateUI.UserPhone,UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
40                     </StackPanel>
41                     <StackPanel>
42                         <Label Foreground="Red" Content="提示:验证全部通过的时候提交按钮可操作!" Width="250"  ></Label>
43                     </StackPanel>
44                     <Button Content="提交" Margin="100,16,0,0" HorizontalAlignment="Left" Command="{Binding SubmitCmd}" />
45                 </StackPanel>
46             </GroupBox>
47
48             <StackPanel>
49                 <DataGrid x:Name="dg1" ItemsSource="{Binding List}" AutoGenerateColumns="False" CanUserAddRows="False"
50                                       CanUserSortColumns="False" Margin="10" AllowDrop="True" IsReadOnly="True" >
51                     <DataGrid.Columns>
52                         <DataGridTextColumn Header="用户姓名" Binding="{Binding UserName}" Width="100" />
53                         <DataGridTextColumn Header="邮箱"  Binding="{Binding UserEmail}" Width="400" />
54                         <DataGridTextColumn Header="电话" Binding="{Binding UserPhone}" Width="100" />
55                     </DataGrid.Columns>
56                 </DataGrid>
57
58             </StackPanel>
59
60         </StackPanel>
61
62     </Grid>
63 </Window>

ViewModel代码:

这边需要注意的是:用户在界面上点击提交按钮的时候去ViewModel 里面寻找名为SubmitCmd的 RelayCommand命令对象,如果找不到,则执行无效果,所以名称一定要对应上,而且需要是公开的访问级别。

CanExcute方法这边用表单是否验证通过来判断命令是否执行,如果返回的是false,则该命令不执行,这时候提交按钮也是不可用(Disable)的。

 1 using GalaSoft.MvvmLight;
 2 using GalaSoft.MvvmLight.CommandWpf;
 3 using MVVMLightDemo.Model;
 4 using System.Collections.ObjectModel;
 5
 6 namespace MVVMLightDemo.ViewModel
 7 {
 8     public class CommandViewModel:ViewModelBase
 9     {
10         public CommandViewModel()
11         {
12             //构造函数
13             ValidateUI = new ValidateUserInfo();
14             List = new ObservableCollection<ValidateUserInfo>();
15         }
16
17         #region 全局属性
18         private ObservableCollection<ValidateUserInfo> list;
19         /// <summary>
20         /// 用户数据列表
21         /// </summary>
22         public ObservableCollection<ValidateUserInfo> List
23         {
24             get { return list; }
25             set { list = value; }
26         }
27
28         private ValidateUserInfo validateUI;
29         /// <summary>
30         /// 当前操作的用户信息
31         /// </summary>
32         public ValidateUserInfo ValidateUI
33         {
34             get { return validateUI; }
35             set
36             {
37                 validateUI = value;
38                 RaisePropertyChanged(() => ValidateUI);
39             }
40         }
41         #endregion
42
43         #region 全局命令
44         private RelayCommand submitCmd;
45         /// <summary>
46         /// 执行提交命令的方法
47         /// </summary>
48         public RelayCommand SubmitCmd
49         {
50             get
51             {
52                 if (submitCmd == null) return new RelayCommand(() => ExcuteValidForm(),CanExcute);
53                 return submitCmd;
54             }
55             set { submitCmd = value; }
56         }
57         #endregion
58
59         #region 附属方法
60         /// <summary>
61         /// 执行提交方法
62         /// </summary>
63         private void ExcuteValidForm()
64         {
65             List.Add(new ValidateUserInfo(){ UserEmail= ValidateUI.UserEmail, UserName = ValidateUI.UserName, UserPhone = ValidateUI.UserPhone });
66         }
67
68         /// <summary>
69         /// 是否可执行(这边用表单是否验证通过来判断命令是否执行)
70         /// </summary>
71         /// <returns></returns>
72         private bool CanExcute()
73         {
74             return ValidateUI.IsValidated;
75         }
76         #endregion
77
78     }
79 }

结果如下:

这是最简单的命令操作了,下篇我们来深入了解下命令和EventToCommand的相关内容。

示例代码下载

转载请标明出处,谢谢

时间: 2024-10-26 03:56:00

利刃 MVVMLight 6:命令基础的相关文章

利刃 MVVMLight

已经很久没有写系列文章了,上一次是2012年写的HTLM5系列,想想我们应该是较早一批使用HTML5做项目的人. 相比我当时动不动100+的粉丝增长和两天3000+的阅读量,MVVM Light只能算小众技术了,也是因为她小众,才更具意义,不希望有人跟我一样网上找案例找半天. 写的初衷也是希望同项目组的同事能更好的融入和接收已有项目.其中两篇<DispatchHelper在多线程和调度中的使用>和<Messenger>是在上林院长课的时候抱着笔记本写的,现在想想挺后悔的, 再回头上

Linux命令基础

Linux命令基础 . 实验目标 熟练基础命令 . 实验步骤 Linux命令行基础 [[email protected] ~]# ls//查看列表目标内容 [[email protected] ~]# ls -l               //以长格式显示 [[email protected] ~]# ls -l /boot/        //显示boot内容 [[email protected] ~]# ls -l /boot /root   // [[email protected] ~

sed命令基础用法

    sed(Stream EDitor)简介 sed是一个流编辑器编辑器,本身是一个管道命令,主要以行为单位处理文本文件,可以将数据进行替换.删除.新增.选取等特定工作:sed并不会处理文本文件本身,而是每当处理一个文件时,按顺序逐行读取到模式空间(内存)中,而后在模式空间中完成编辑,把编辑的结果输出到屏幕上,接着处理下一行,反复操作,直到文件结尾. 模式空间:将读取的内容放在内存中的一块区域编辑,这些内存空间就称为模式空间 格式: sed [options]    'Address Com

北大,awk 命令基础练习

北大,awk 命令基础练习 Red Hat Enterprise Linux Version 5.3 Get the latest news about the world's Open Source Leader Red Hat Network Manage your system dffectively through Red Hat Network Global Learning Services You've got Red Hat Enterprise Linux,now get th

Linux常用命令总结——命令基础

有人感觉Linux命令行操作是件非常神秘和高难度的事,其实并不然,只要我们静下心来了解一下Linux命令行下操作的相关基础知识,就会发现命令行操作并没有想象的那么难.命令行操作的特点可以用四个字概括"简单高效".在图形界面下需要点几十次鼠标的工作只需要一两条命令即可完成.我们在学习具体命令之前,先要掌握命令的基础知识,掌握了这些,学习命令就是件非常简单的事了. Linux命令使用格式: 命令  [选项]  [参数] 命令.选项.参数之间使用空格分隔. 选项:用于调节命令的具体功能. 短

shell命令基础

1.修改密码 使用 passwd 命令修改密码. 该命令如果在 root 用户下执行,则修改的是 root 用户的密码. 2.获取帮助 使用 ls --help 命令获取帮助. 1 [[email protected] ~]$ ls --help 2 用法:ls [选项]... [文件]... 3 列出 FILE 的信息(默认为当前目录). 4 如果不指定-cftuvSUX 或--sort 选项,则根据字母大小排序. 5 6 长选项必须使用的参数对于短选项时也是必需使用的. 7 -a, --al

ansible概述、安装、命令基础

ansible概述 Ansible是2013年推出的一款IT自动化和DevOps软件,目前由Redhat已签署Ansible收购协议.其是基于Python研发,糅合了很多老运维工具的优点.实现了批量操作系统配置,批量程序的部署,批量运行命令等功能. 为什么要选择ansible? ? ansible优点 是仅需要ssh和Python即可使用 无客户端 ? ansible功能强大,模块丰富 ? 上手容易门槛低 ? 基于 python 开发,做二次开发更容易 ? 使用公司比较多,社区活跃 ansibl

ansible命令基础

7.ansible命令基础7.1语法7.1.1ansibleansible <host-pattern> [-f forks] [-m module_name] [-a args]host-pattern:对哪些主机生效,可以直接跟ip,可以调用hosts文件中的定义-f forks:并发线程数,即一批处理多少个主机-m module:使用哪个模块-a args:模块特有的参数,有的有默认值-i 文件名 相当于-inventory-file=文件,可以指定hosts文件7.1.2ansible

第5章 LINUX文件及目录管理命令基础

第5章 LINUX文件及目录管理命令基础5.1 操作LINUX必知必会基础知识5.1.1 Linux命令行组成结构root @ oldboy ~ # :当前用户名 分隔符 主机名 当前用户登陆后的位置,这是个变量 提示符 5.1.2 基本的Linux命令操作语法示例5.1.3 Linux与Windows的目录结构对比5.2 Linux文件及目录核心命令5.2.1 pwd:显示当前所在位置信息"print working directory"-L:逻辑路径:-P:物理路径系统Bash命令

Linux命令基础-rpm

命令简介 rpm命令是RPM软件包的管理工具.rpm原本是Red Hat Linux发行版专门用来管理Linux各项套件的程序,由于它遵循GPL规则且功能强大方便,因而广受欢迎.逐渐受到其他发行版的采用.RPM套件管理方式的出现,让Linux易于安装,升级,间接提升了Linux的适用度. 命令选项 -a:查询所有套件: -b<完成阶段><套件档>+或-t <完成阶段><套件档>+:设置包装套件的完成阶段,并指定套件档的文件名称: -c:只列出组态配置文件,本