这篇来讨论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的使用所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)