WPF MVVM从入门到精通4:命令和事件
WPF MVVM从入门到精通5:PasswordBox的绑定
WPF MVVM从入门到精通6:RadioButton等一对多控件的绑定
这一部分我们要做的事情,是把点击登录按钮的事件也在ViewModel里实现。若不是用MVVM模式,可能XAML文件里是这样的:
<Button Grid.Row="3" Grid.ColumnSpan="2" Content="登录" Width="200" Height="30" Click="Button_Click"/>
而跟XAML文件相关的CS文件里则是这样的:
private void Button_Click(object sender, RoutedEventArgs e)
{
//业务处理逻辑代码
}
如此一来,前端和后端的代码又耦合在一起了。其实,命令和事件都是可以绑定的,就像数据一样。
我们先来了解一下命令。ICommand是所有命令的接口,它主要完成两件事情,这个命令能否被执行,以及执行命令。
event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter);
public void Execute(object parameter);
例如当用户名为空时,我们可能会禁用按钮。当登录按钮跟一个命令绑定在一起时,CanExecute会不断被执行,如果返回false,按钮的IsEnabled属性也会被置为false。
一般情况下,我们需要继承ICommand接口来进行开发。
using System;
using System.Windows.Input;
namespace LoginDemo.ViewModel.Common
{
/// <summary>
/// 命令基类
/// </summary>
public class BaseCommand : ICommand
{
public event EventHandler CanExecuteChanged
{
add
{
if (_canExecute != null)
{
CommandManager.RequerySuggested += value;
}
}
remove
{
if (_canExecute != null)
{
CommandManager.RequerySuggested -= value;
}
}
}
public bool CanExecute(object parameter)
{
if (_canExecute == null)
{
return true;
}
return _canExecute(parameter);
}
public void Execute(object parameter)
{
if (_execute != null && CanExecute(parameter))
{
_execute(parameter);
}
}
private Func<object, bool> _canExecute;
private Action<object> _execute;
public BaseCommand(Action<object> execute, Func<object, bool> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public BaseCommand(Action<object> execute) :
this(execute, null)
{
}
}
}
BaseCommand的功能很简单,就是执行命令前先判断一下命令能不能执行。
然后我们就可以绑定命令了,在后端这样写:
private BaseCommand clickLoginCommand;
public BaseCommand ClickLoginCommand
{
get
{
if(clickLoginCommand==null)
{
clickLoginCommand = new BaseCommand(new Action<object>(o =>
{
//执行登录逻辑
}));
}
return clickLoginCommand;
}
}
前端这样写:
<Button Grid.Row="3" Grid.ColumnSpan="2" Content="登录" Width="200" Height="30" Command="{Binding ClickLoginCommand}"/>
点击按钮执行登录逻辑的代码就这样完成了。但不要急着复制代码,因为我们不打算使用命令。
我们知道,对于按钮的操作,不一定是点击,可能是鼠标划过,可能是鼠标右击。那Command触发的是什么呢?就是点击,没有其他了。对于其他控件,例如是输入框,Command又代表什么呢?文本改变事件能用Command吗?这些问题让我们感到困惑,所以一般在项目中,我都只会使用事件,而不会使用命令(即使是单击事件)。
BaseCommand这个类还可以留着,我们后面还需要使用的。在引入事件之前,我们需要先引用一个dll:System.Windows.Interactivity.dll。这个dll并不是.NET Framework的标配,它是Blend的一个类库。可以在扩展的程序集里找到:
如果没有找到(我安装VS2017后就没有找到),需要安装以下库才有:
好了,引用了System.Windows.Interactivity.dll后,我们就可以开始讲事件了。
有些事件是有参数的,例如鼠标移动这个事件,会带上鼠标的位置。但我们之前使用的命令,默认传入的参数是null。为了能够传递参数,我们需要先定义一个事件基类:
using System.Windows;
using System.Windows.Input;
using System.Windows.Interactivity;
namespace LoginDemo.ViewModel.Common
{
/// <summary>
/// 事件命令
/// </summary>
public class EventCommand : TriggerAction<DependencyObject>
{
protected override void Invoke(object parameter)
{
if (CommandParameter != null)
{
parameter = CommandParameter;
}
if (Command != null)
{
Command.Execute(parameter);
}
}
/// <summary>
/// 事件
/// </summary>
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand), typeof(EventCommand), new PropertyMetadata(null));
/// <summary>
/// 事件参数,如果为空,将自动传入事件的真实参数
/// </summary>
public object CommandParameter
{
get { return (object)GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.Register("CommandParameter", typeof(object), typeof(EventCommand), new PropertyMetadata(null));
}
}
现在,我们可以在ViewModel里增加如下代码:
private BaseCommand loginClick;
/// <summary>
/// 登录事件
/// </summary>
public BaseCommand LoginClick
{
get
{
if(loginClick==null)
{
loginClick = new BaseCommand(new Action<object>(o =>
{
//执行登录逻辑
}));
}
return loginClick;
}
}
然后在XAML文件里,先加入i这个命名空间:xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity",然后修改按钮的代码:
<Button Grid.Row="3" Grid.ColumnSpan="2" Content="登录" Width="200" Height="30">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<c:EventCommand Command="{Binding LoginClick}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
上面的代码指出,Click这个事件,绑定到了LoginClick这个属性。当我们点击按钮的时候,LoginClick里面的Action就会被执行。
WPF MVVM从入门到精通4:命令和事件的更多相关文章
- WPF MVVM从入门到精通8:数据验证
原文:WPF MVVM从入门到精通8:数据验证 WPF MVVM从入门到精通1:MVVM模式简介 WPF MVVM从入门到精通2:实现一个登录窗口 WPF MVVM从入门到精通3:数据绑定 WPF M ...
- WPF MVVM从入门到精通6:RadioButton等一对多控件的绑定
原文:WPF MVVM从入门到精通6:RadioButton等一对多控件的绑定 WPF MVVM从入门到精通1:MVVM模式简介 WPF MVVM从入门到精通2:实现一个登录窗口 WPF MVVM ...
- WPF MVVM从入门到精通7:关闭窗口和打开新窗口
原文:WPF MVVM从入门到精通7:关闭窗口和打开新窗口 WPF MVVM从入门到精通1:MVVM模式简介 WPF MVVM从入门到精通2:实现一个登录窗口 WPF MVVM从入门到精通3:数据绑定 ...
- WPF MVVM从入门到精通5:PasswordBox的绑定
原文:WPF MVVM从入门到精通5:PasswordBox的绑定 WPF MVVM从入门到精通1:MVVM模式简介 WPF MVVM从入门到精通2:实现一个登录窗口 WPF MVVM从入门到精通 ...
- WPF MVVM从入门到精通3:数据绑定
原文:WPF MVVM从入门到精通3:数据绑定 WPF MVVM从入门到精通1:MVVM模式简介 WPF MVVM从入门到精通2:实现一个登录窗口 WPF MVVM从入门到精通3:数据绑定 WPF ...
- WPF MVVM从入门到精通2:实现一个登录窗口
原文:WPF MVVM从入门到精通2:实现一个登录窗口 WPF MVVM从入门到精通1:MVVM模式简介 WPF MVVM从入门到精通2:实现一个登录窗口 WPF MVVM从入门到精通3:数据绑定 ...
- WPF MVVM从入门到精通1:MVVM模式简介
原文:WPF MVVM从入门到精通1:MVVM模式简介 WPF MVVM从入门到精通1:MVVM模式简介 WPF MVVM从入门到精通2:实现一个登录窗口 WPF MVVM从入门到精通3:数据绑定 W ...
- WPF/MVVM Quick Start Tutorial - WPF/MVVM 快速入门教程 -原文,翻译及一点自己的补充
转载自 https://www.codeproject.com/articles/165368/wpf-mvvm-quick-start-tutorial WPF/MVVM Quick Start T ...
- Git版本控制软件结合GitHub从入门到精通常用命令学习手册(转)
简要参考:http://www.tuicool.com/articles/mEvaq2 http://gitref.org/zh/index.html GIT 学习手册简介 本站为 Git 学习参考手 ...
随机推荐
- C语言基础笔试题一
1.下面的代码输出什么?为什么? void foo(void) { unsigned int a = 6; int b = -20; (a+b > 6)?puts(">6&quo ...
- 由JDK源码学习HashMap
HashMap基于hash表的Map接口实现,它实现了Map接口中的所有操作.HashMap允许存储null键和null值.这是它与Hashtable的区别之一(另外一个区别是Hashtable是线程 ...
- css3-鼠标经过产品列表 图片放大 显示文字 (兼容IE9以上 不含IE9)
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8" /> <title&g ...
- Java虚拟机12:虚拟机性能监控与故障处理工具
前言 定位系统问题的时候,知识.经验是基础,数据是依据,工具是运用知识处理数据的手段.这里说的数据包括:运行日志.异常堆栈.GC日志.线程快照.堆转储快照等.经常使用适当的虚拟机监控和分析的工具可以加 ...
- 坑之OJ-玄学、不可抗力
自家学校OJ网站上的题目,很玄学,不知道哪里出的问题. 这个OJ链接的题目没有问题的. https://www.luogu.org/problemnew/show/P1981 #include < ...
- 文件断点上传,html5实现前端,java实现服务器
断点上传能够防止意外情况导致上传一半的文件下次上传时还要从头下载,网上有很多关于断点的实现,这篇文章只是从前到后完整的记录下一个可用的实例,由于生产环境要求不高,而且就是提供给一两个人用,所以我简化了 ...
- ERDAS IMAGINE 2014 32位 破解安装
1. 安装Install ERDAS Foundation 2014 2. 安装ERDAS IMAGINE 2014 32位 3. 安装Intergraph ...
- ASP.Net GridView 基础
SP.NET 在开发过程中经常使用的微软提供的服务器控件(GridView),但在开发中很少使用界面化来操作.导致了有点不太会使用界面化操作了,还有就是一些不经常使用的属性也没什么印象了,在网上找了好 ...
- ASP.NET Core Middleware (转载)
What is Middleware? Put simply, you use middleware components to compose the functionality of your A ...
- windows 建立任务执行计划 自动执行脚本
对于windows服务器网站如果要定时执行脚本,则需要在windows控制面板里找到 管理工具,点击任务计划程序,创建任务填写任务名称 触发器里新建触发条件,设置间隔时间 在操作项,新建触发时需要做的 ...