基于wpf的相关设计问题-Command的使用

基于wpf的相关设计问题-Command的使用,第1张

概述     这篇来讨论Command基于ViewModel的基本使用. 以prism内置Command Demo为例子,效果图如下 View相对应的ViewModel 1.OrderEditorView的Model就是OrdersEditorPresentationModel了 2.SaveAllOrdersCommand可以在数据通过验证后同时保存,即同时触发三个Command 3.每个Order

     这篇来讨论Command基于viewmodel的基本使用.

以prism内置Command Demo为例子,效果图如下

VIEw相对应的viewmodel

1.OrderEditorVIEw的Model就是OrdersEditorPresentationModel了

2.SaveAllOrdersCommand可以在数据通过验证后同时保存,即同时触发三个Command

3.每个Order都有一个Save的Command,这里Orders是一个OrderPresentationModel列表,注意这里OrdersEditorPresentationModel有一个VIEw的属性(因为我们还没有Presenter来 *** 作调配)

一.路由命令

 

路由命令由RoutedCommand实现,必须由当前使用的控件的父级控件在CommandBindings集合中注册命令.

这里需要注意的是wpf内置的Command,如ApplicationCommands类有很多Command,其只是定义而已,并未真正实现,像TextBox这些控件内置已经实现了一些,复制粘贴功能,所以不要以为是内置Command实现,在注册这些内置的Command时,必须手动实现才可以.

有些控件实现了内置的Command逻辑,你可以复用这些功能,这时候你就必须指定CommandTarget这个属性

下面我们来看一下做法

1.CreateCommandBinding负责注册命令,注册的Model均继承自CommandModel

CommandModel commandModel = e.NewValue as CommandModel;if (commandModel != null){    element.CommandBindings.Add(new CommandBinding(commandModel.Command,commandModel.OnExecute,commandModel.OnqueryEnabled));}

2.Model

/// <summary>/// Model for a command/// </summary>public abstract class CommandModel{    public CommandModel()    {        _routedCommand = new RoutedCommand();    }    /// <summary>    /// Routed command associated with the model.    /// </summary>    public RoutedCommand Command    {        get { return _routedCommand; }    }    /// <summary>    /// Determines if a command is enabled. OverrIDe to provIDe custom behavior. Do not call the    /// base version when overrIDing.    /// </summary>    public virtual voID OnqueryEnabled(object sender,CanExecuteRoutedEventArgs e)    {        e.CanExecute = true;        e.Handled = true;    }    /// <summary>    /// Function to execute the command.    /// </summary>    public abstract voID OnExecute(object sender,ExecutedRoutedEventArgs e);    private RoutedCommand _routedCommand;}

 

3.使用方法,这里分析一下其用法

CreateCommandBinding附加属性Command省却了手动注册Command这一步骤

Command还是绑定viewmodel的一个属性,但其处理的对象本应该在viewmodel中的,这里却用CommandParameter将一个与viewmodel绑定的参考重新传了进去,这是一个不好的地方.这是可以通过设计来改善的,因为在viewmodel定义出来的Command大多数是 *** 作viewmodel对象的,只要想办法把定义的CommandModel的Command提取到viewmodel中,就可以直接 *** 作viewmodel了,依靠CommandParamter来传值并不是一个好的办法.但注册Command这一步骤还是少不了的.

<buttonCommand="{Binding UnblockCommandModel.Command}"CommandParameter="{Binding Path=SelectedItem,Elementname=_skillList}"luna:CreateCommandBinding.Command="{Binding UnblockCommandModel}">

    二.由prism提供的DelegateCommand和CompositeCommand


DelegateCommand实现了ICommand接口(SaveOrderCommand便是一个DelegateCommand),wpf有一些控件实现了ICommandSource接口,具有Command属性和CommandParameter属性,两者皆为依赖属性,这就为数据绑定提供了便利.CompositeCommand的职责在于实现多个Command同时执行.如wpf的button控件(注意:silverlight当前版本很多控件并未具有Command属性,所以prism使用附加属性的形式实现了这一过程),如下

<button GrID.Row="6" GrID.Column="1" Content="Save"         cal:Click.Command="{Binding Path=SaveOrderCommand}"          />

 

wpf版本的

<button        GrID.Row="6" GrID.Column="1" Content="Save"         Command="{Binding SaveOrderCommand}"></button>

 

其在viewmodel中的定义方法(参考包含Execute,CanExecute两个委托)

this.SaveOrderCommand = new DelegateCommand<object>(this.Save,this.CanSave);

 

CompositeCommand有两个方法用于注册(RegisterCommand)和注销(UnregisterCommand)想要同时触发Command的方法.其可以是一个静态属性

<button Command="{x:Static inf:OrdersCommands.SaveAllOrdersCommand}">Save All Orders</button>

 

这种做法其实也是为了把VIEw和逻辑分开,将事件替换成Command,从而直接对viewmodel进行 *** 作.

三.阻止Command的触发

 

由于RoutedCommand在设计时,做了相对多的封装,所以具备的功能也比较多.我们举个例子,在我们删除数据时,常要用MessageBox来提醒用户”确认要删除吗?”

CommandManager提供了4个额外的附加事件,PrevIEw事件可以通过设置ExecutedRoutedEventArgs的Handled为True阻止Command的触发

<button CommandManager.PrevIEwExecuted="button_PrevIEwExecuted"      Command="vm:Personviewmodel.SpeakCommand"      CommandParameter="Howdy partner!"      Content="Speak"      margin="0,6,0"      WIDth="60"      />

 

private voID button_PrevIEwExecuted(object sender,System.windows.input.ExecutedRoutedEventArgs e){    MessageBoxResult result = MessageBox.Show("Are you sure?","MessageBox",MessageBoxbutton.OKCancel);    if (result == MessageBoxResult.OK)    {        e.Handled = false;    }    else    {        e.Handled = true;    }}

 

目前prism的DelegateCommand并为提供类似功能,你也可以通过在PrevIEwMouseleftbuttonDown事件中设置Handled为True阻止其触发.至于CallBack回调更是没有了,这些就需要我们自己想了.这也是在开发中常用到的问题.

@H_695_403@ 总结

以上是内存溢出为你收集整理的基于wpf的相关设计问题-Command的使用全部内容,希望文章能够帮你解决基于wpf的相关设计问题-Command的使用所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1061948.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存