博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【UWP】使用Action代替Command
阅读量:6322 次
发布时间:2019-06-22

本文共 7573 字,大约阅读时间需要 25 分钟。

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

Xaml:

ViewModel

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

  

使用如下

Xaml

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
///     /// 带参数的Action    ///     [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
), typeof (WdCallMethodAction), new PropertyMetadata(new List
())); ///
/// 方法名:参数有?,eventArgs,sender,dataContext /// eg:Test /// eg:Test(?,?) /// eg:Test(sender,?,?) /// public string MethodName { get { return (string) GetValue(MethodNameProperty); } set { SetValue(MethodNameProperty, value); } } public ICollection
Parameters { get { return (ICollection
) 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
parameters) { var start = methodName.IndexOf('('); var end = methodName.IndexOf(')'); MethodInfo methodInfo; if (start >= 0 && end >= 0) { var paras = methodName.Substring(start + 1, end - start - 1) .Split(new[] {
',', ' '}, StringSplitOptions.RemoveEmptyEntries); methodName = MethodName.Substring(0, start); var allParameter = new List
(); 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[0]); methodInfo.Invoke(TargetObject, null); } } }
WdCallMethodAction

Xaml

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://xzcaa.baihongyu.com/

你可能感兴趣的文章
locate 命令(转)
查看>>
JUnit入门
查看>>
Linux内存管理大图
查看>>
sql中exists,not exists的用法
查看>>
WebGIS中兴趣点简单查询、基于Lucene分词查询的设计和实现
查看>>
实现android activity之间的跳转
查看>>
XMPP协议实现原理介绍
查看>>
HttpWebRequest类
查看>>
Eureka 的 Application Client client的执行演示样例
查看>>
从决策树学习谈到贝叶斯分类算法、EM、HMM
查看>>
Ubuntu 14.04 字体设置
查看>>
【转载】VS配置路径和宏
查看>>
Appium移动自动化测试(四)--one demo
查看>>
jQuery来源学习笔记:扩展的实用功能
查看>>
STM32 CRC-32 Calculator Unit
查看>>
BZOJ2790 : [Poi2012]Distance
查看>>
jenkins 安装 SVN Publisher 后向 svn 提交代码报错: E170001: Authentication required for...
查看>>
伪异步IO理解
查看>>
成为JAVA GC专家系列
查看>>
我的编程之路(十八) 团队开发
查看>>