在Xaml中,说到绑定,我们用的最多的应该就是ICommand了,通过Command实现ViewModel到View之间的命令处理,例如Button默认就提供了Command支持,如下

Xaml:

    <Button Content="TestWithCommand" Command="{Binding TestCommand}" />

ViewModel

    /// <summary>Provides a base implementation of the <see cref="ICommand"/> interface. </summary>
public abstract class CommandBase : ICommand
{
/// <summary>Gets a value indicating whether the command can execute in its current state. </summary>
public abstract bool CanExecute { get; } /// <summary>Defines the method to be called when the command is invoked. </summary>
protected abstract void Execute(); /// <summary>Tries to execute the command by checking the <see cref="CanExecute"/> property
/// and executes the command only when it can be executed. </summary>
/// <returns>True if command has been executed; false otherwise. </returns>
public bool TryExecute()
{
if (!CanExecute)
return false;
Execute();
return true;
} /// <summary>Occurs when changes occur that affect whether or not the command should execute. </summary>
public event EventHandler CanExecuteChanged; void ICommand.Execute(object parameter)
{
Execute();
} bool ICommand.CanExecute(object parameter)
{
return CanExecute;
}
} /// <summary>Provides an implementation of the <see cref="ICommand"/> interface. </summary>
public class RelayCommand : CommandBase
{
private readonly Action _execute;
private readonly Func<bool> _canExecute; /// <summary>Initializes a new instance of the <see cref="RelayCommand"/> class. </summary>
/// <param name="execute">The action to execute. </param>
public RelayCommand(Action execute)
: this(execute, null)
{ } /// <summary>Initializes a new instance of the <see cref="RelayCommand"/> class. </summary>
/// <param name="execute">The action to execute. </param>
/// <param name="canExecute">The predicate to check whether the function can be executed. </param>
public RelayCommand(Action execute, Func<bool> canExecute)
{
if (execute == null)
throw new ArgumentNullException(nameof(execute)); _execute = execute;
_canExecute = canExecute;
} /// <summary>Defines the method to be called when the command is invoked. </summary>
protected override void Execute()
{
_execute();
} /// <summary>Gets a value indicating whether the command can execute in its current state. </summary>
public override bool CanExecute => _canExecute == null || _canExecute();
}

RelayCommand

    public class MainPageViewModel
{
public ICommand TestCommand { get; private set; }
public MainPageViewModel()
{
TestCommand = new RelayCommand(TestCmd);
} public void TestCmd()
{
Debug.WriteLine("TestCmd");
}
}

上面只是一个最简单的例子,但是如果需要绑定的方法很多的时候,就会有一大堆的ICommand属性定义,并且也需要初始化,代码看起来特别臃肿

下面我们使用Behavior代替Command完成方法的绑定

在WinRT中,Behavior是以组件的方法安装到VS上的,而在UWP上,官方并没有提供对应的组件,我们可以通过Nuget添加UWP版本的Behavior组件:

  http://www.nuget.org/packages/Microsoft.Xaml.Behaviors.Uwp.Managed/

使用如下

Xaml

    <Button Content="TestWithAction">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<core:CallMethodAction TargetObject="{Binding}" MethodName="Test"/>
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</Button>

ViewModel

    public class MainPageViewModel
{
public void Test()
{
Debug.WriteLine("test");
}
}

  官方提供的Behavior更加灵活,可以自己配置事件名,和对应的方法名称,并且我们在ViewModel中不需要写ICommand等代码了,看起来更简洁明了,但是还有个问题,

有时候我们需要用到事件的参数,有时候我们需要用到触发事件的控件,有时候我们还需要控件对应的DataContext,而官方提供的库中并不提供带参数的方法,下面我们对其进行修改一下,让其支持参数传递,并且支持多参数

自定义一个支持参数Action

    public class Parameter : DependencyObject
{
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value", typeof (object), typeof (Parameter), new PropertyMetadata(default(object))); public object Value
{
get { return (object) GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
}

Parameter

    /// <summary>
/// 带参数的Action
/// </summary>
[ContentProperty(Name = "Parameters")]
public sealed class WdCallMethodAction : DependencyObject, IAction
{
public static readonly DependencyProperty MethodNameProperty = DependencyProperty.Register("MethodName",
typeof (string), typeof (WdCallMethodAction), new PropertyMetadata(null)); public static readonly DependencyProperty TargetObjectProperty = DependencyProperty.Register("TargetObject",
typeof (object), typeof (WdCallMethodAction), new PropertyMetadata(null)); public static readonly DependencyProperty ParametersProperty = DependencyProperty.Register(
"Parameters", typeof (ICollection<Parameter>), typeof (WdCallMethodAction),
new PropertyMetadata(new List<Parameter>())); /// <summary>
/// 方法名:参数有?,eventArgs,sender,dataContext
/// eg:Test
/// eg:Test(?,?)
/// eg:Test(sender,?,?)
/// </summary>
public string MethodName
{
get { return (string) GetValue(MethodNameProperty); }
set { SetValue(MethodNameProperty, value); }
} public ICollection<Parameter> Parameters
{
get { return (ICollection<Parameter>) GetValue(ParametersProperty); }
set { SetValue(ParametersProperty, value); }
} public object TargetObject
{
get { return GetValue(TargetObjectProperty); }
set { SetValue(TargetObjectProperty, value); }
} public object Execute(object sender, object parameter)
{
InvokeMethod(MethodName, sender, parameter, TargetObject, Parameters);
return true;
} public void InvokeMethod(string methodName, object sender, object eventArgs, object dataContext,
ICollection<Parameter> parameters)
{
var start = methodName.IndexOf('(');
var end = methodName.IndexOf(')'); MethodInfo methodInfo; if (start >= && end >= )
{
var paras = methodName.Substring(start + , end - start - )
.Split(new[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries); methodName = MethodName.Substring(, start); var allParameter = new List<object>();
var enumerator = parameters.GetEnumerator();
foreach (var para in paras)
{
switch (para)
{
case "?":
enumerator.MoveNext();
allParameter.Add(enumerator.Current);
break;
case "eventArgs":
allParameter.Add(eventArgs);
break;
case "sender":
allParameter.Add(sender);
break;
case "dataContext":
allParameter.Add(dataContext);
break;
default:
throw new NotImplementedException(string.Format("没有实现该参数:{0}", para)); }
} var paramCount = paras.Length;
methodInfo = TargetObject.GetType().GetRuntimeMethods()
.FirstOrDefault(m => Equals(m.Name, methodName) && m.GetParameters().Count() == paramCount); methodInfo.Invoke(TargetObject, allParameter.ToArray());
}
else
{
methodInfo = TargetObject.GetType().GetRuntimeMethod(methodName, new Type[]);
methodInfo.Invoke(TargetObject, null);
} }
}

WdCallMethodAction

Xaml

    <Button x:Name="btn" Content="TestWithActionAndParameter">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<command:WdCallMethodAction TargetObject="{Binding}" MethodName="Test(eventArgs, sender, dataContext, ?,?)">
<command:Parameter Value="32"/>
<!-- 参数暂不支持绑定(下面方式为空)-->
<command:Parameter Value="{Binding ElementName=btn}"/>
</command:WdCallMethodAction>
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</Button>

ViewModel

    public void Test(RoutedEventArgs eventArgs, FrameworkElement sender, MainPageViewModel dataContext, Parameter param1, object param2)
{
Debug.WriteLine("sender:{0}", sender);
Debug.WriteLine("eventArgs:{0}", eventArgs);
Debug.WriteLine("dataContext:{0}", dataContext);
Debug.WriteLine("param1:{0}", param1);
Debug.WriteLine("param2:{0}", param2);
}

注:目前Parameter暂不支持绑定

demo

  http://files.cnblogs.com/files/bomo/CommandInvokeDemo.zip

【UWP】使用Action代替Command的更多相关文章

  1. UWP开发之Mvvmlight实践三:简单MVVM实例开发(图文详解付代码)

    在做MVVM各种框架对比之前,我觉得有必要先自己做一个简单的MVVM实现案例比较好,这样就可以看到自己实现的时候有那些不方便的地方.而各种框架又是怎么解决我们这些麻烦的. 案例介绍:用户登录画面,没有 ...

  2. struts2 CVE-2012-0392 S2-008 Strict DMI does not work correctly allows remote command execution and arbitrary file overwrite

    catalog . Description . Effected Scope . Exploit Analysis . Principle Of Vulnerability . Patch Fix 1 ...

  3. 第 12 章 命令模式【Command Pattern】

    以下内容出自:<<24种设计模式介绍与6大设计原则>> 今天讲命令模式,这个模式从名字上看就很简单,命令嘛,老大发命令,小兵执行就是了,确实是这个意思,但是更深化了,用模式来描 ...

  4. 24种设计模式--命令模式【Command Pattern】

    今天讲命令模式,这个模式从名字上看就很简单,命令嘛,老大发命令,小兵执行就是了,确实是这个意思,但是更深化了,用模式来描述真实世界的命令情况.正在看这本书的你,我猜测分为两类:已经工作的和没有工作的, ...

  5. 【Unity与23种设计模式】命令模式(Command)

    GoF中定义: "将请求封装成为对象,让你可以将客户端的不同请求参数化,并配合队列.记录.复原等方法来执行请求的操作." 实现命令模式的标准在于: 当请求被对象化后,对于请求对象是 ...

  6. 行为型---命令模式(Command Pattern)

    命令模式的定义 命令模式属于对象的行为型模式.命令模式是把一个操作或者行为抽象为一个对象中,通过对命令的抽象化来使得发出命令的责任和执行命令的责任分隔开.命令模式的实现可以提供命令的撤销和恢复功能. ...

  7. 设计模式のCommand Pattern(命令模式)----行为模式

    一.产生背景 熟悉计算机的同学应该清楚,用户发出各种命令,CPU执行命令,OS负责调度.命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式.请求以命令的形式包裹在对象 ...

  8. 行为型模式之Command模式

    命令模式将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化, 并且可以对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能. 概念描述 把命令的调用者与执行者分开,使双方不必关心对方是 ...

  9. 大话设计模式--命令模式 Command -- C++实现实例

    1. 命令模式: 将请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作. 命令模式有点: a. 较容易的设计一个命令队列 b. 在需要的的情况 ...

随机推荐

  1. iOS 打包iPa

    http://blog.fir.im/how-to-build-adhoc-ipa/ 之前都是打包好ipa然后发送给客户,特麻烦,fir.im网站不错 迅速获取自己手机的udid:  http://f ...

  2. 爱上MVC~MVC4模型验证可以放在前端

    回到目录 MVC4.0推出后,在模型验证上有了一个新的改近,它支持前端验证,即在用户POST之前,如果验证失败,则Action(POST方式的)不会被执行,而直接停留在原视图,这对于用户体验是好的,它 ...

  3. Java程序员的日常 —— 多进程开发IO阻塞问题

    本篇仍旧是源于最近的工作,总结一下纪念那些年埋下的坑... 背景故事 需求:"使用进程方式启动另一个程序!" 开发:"OK! Runtime.getRuntime().e ...

  4. SSM 三大框架整合

    上一篇已经讲了整个各个子模块的创建过程以及它们之间的依存关系, 那么这一篇就来正式的整合三大框架(SSM)了. 1, 准备环境1.1 为每个War包工程创建一个Server 那么 添加了Server后 ...

  5. MyBatis学习总结(六)——调用存储过程

    一.提出需求 查询得到男性或女性的数量, 如果传入的是0就女性否则是男性 二.准备数据库表和存储过程 1 create table p_user( 2 id int primary key auto_ ...

  6. Python中的字符串与字符编码

    本节内容: 前言 相关概念 Python中的默认编码 Python2与Python3中对字符串的支持 字符编码转换 一.前言 Python中的字符编码是个老生常谈的话题,同行们都写过很多这方面的文章. ...

  7. Python中的魔法方法

    1.什么是魔法方法? 魔法方法就是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而这一 ...

  8. 实用的开放源码的Excel导入导出类库 CarlosAg ExcelXmlWriter

    做企业管理软件经常会遇到要把数据导出成EXCEL格式,目前市面上有很多工具类库可以实现此功能.CarlosAg ExcelXmlWriter是其中之一,它绿色小巧,免安装,又源码开放,我在项目中一直以 ...

  9. 找到SQL Server的序列号

          有时候希望获取当前机器上安装的SQL Server序列号,但注册表中序列号是经过加密的,因此我写了一个小工具获取当前SQL Server的序列号.程序比较粗糙,没有做错误验证.       ...

  10. 【WP8.1开发】认识后台任务

    在手机上,使用后台,不像电脑上那么随意,准确地讲嘛,在移动平台上,后台任务都有严格的限制.至于说为什么会有这么多限制,我估计初衷很明显——保证系统的性能不受某个或某几个应用的负面影响:另外就是出于安全 ...