微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!
Mvvm Light Toolkit for wpf/silverlight系列之Command和Events
<Button Command="{Binding SimpleCommand}" Content="简单命令" />
viewmodel:
public Mainviewmodel()
- ...
-
- SimpleCommand = new RelayCommand
- (
- () => CommandResult = "执行简单命令"
- );
注意:SL4才开始支持Command属性绑定,之前的版本不能使用Command属性绑定
CanExecute命令绑定示例:
xaml:
Button Command="{Binding CanExecuteCommand}" Content="CanExecute命令" Margin="5,5,0"/>
- CheckBox x:Name="chkCanClick" IsChecked="{Binding CanClick,Mode=TwoWay}"
- Content="勾上复选框,CanExecute命令按钮才能变为可用"/>
viewmodel:
bool _CanClick;
- bool CanClick
- get { return _CanClick; }
- set
- {
- if (_CanClick == value)
- return;
- _CanClick = value;
- RaisePropertyChanged("CanClick");
-
-
- CanExecuteCommand.RaiseCanExecuteChanged();
- }
- ...
- CanExecuteCommand = (
- () =>
- {
- CommandResult = "执行CanExecute命令";
- },
- () => CanClick
- );
- ...
- }
与简单命令绑定不同的是,CanExecuteCommand构造函数包含两个参数,第二个参数的返回值表示是否可以在按钮上执行命令操作,返回False,则不能在按钮上执行命令,因此按钮为不可用,返回True,则能够在按钮上执行命令,按钮可用。以上示例中,CanExecute返回值与CheckBox的IsChecked属性关联,这样更改CheckBox的勾选状态,按钮的可用状态会随之更改。
带参数的命令绑定示例:
xaml:
Button Command="{Binding ParamCommand}" Content="带参数的CanExecute命令"
- CommandParameter="{Binding CanClick,Mode=OneWay}" Margin="5,0); background-color:inherit; font-weight:bold">/>
viewmodel:
ParamCommand = new RelayCommand<bool?>
- (p) =>
- {
- CommandResult = string.Format("执行带参数的命令(参数值:{0})", p);
- },108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px"> (p) => p??false
- );
- }
这里ParamCommand接收TextBox的值作为参数,泛型版本表示参数类型为string,此时Execute和CanExecute参数也必须是带参数的版本。
注意:
1、在SL4中带参数的CanExecute与不带参数的CanExecute之间的区别;带参数的CanExecute,与参数绑定的属性(CanClick)更改,会自动触发命令的CanExecute方法,而不带参数的CanExecute方法,则需要手动调用CanExecuteCommand.RaiseCanExecuteChanged()方法更新按钮的可用状态。
2、在WPF中,RelayCommand通过CommandManager不停地侦听按钮的CanExecute的状态,因此WPF中按钮的CanExecute状态会随时响应CanExecute方法中的更改,WPF中可以不调用命令的RaiseCanExecuteChanged方法
三、使用行为绑定命令
Command属性绑定只能绑定ICommandSource类型的控件的点击事件,对于其他控件事件,比如TextChanged事件,不能直接绑定到Command,这时我们可以使用Blend的InvokeCommandAction行为来绑定事件到命令,使用步骤如下:
用Blend4打开解决方案,选中要触发事件的控件,比如TextBox,在资产面板中选择行为,在列表中选择InvokeCommandAction,如图:

双击InvokeCommandAction后会为TextBox生成InvokeCommandAction行为,在属性栏可以设置行为的属性:

在EventName栏选择触发的事件名称TextChanged,Command绑定跟Button的绑定方式一样,最后我们生成的代码如下:
xaml:
TextBox x:Name="TextBox1" Margin="5,0" Width="100">
- i:Interaction.Triggers>
- i:EventTrigger EventName="TextChanged" i:InvokeCommandAction Command="{Binding BehavIoUrCommand, Mode=OneWay}"
- CommandParameter="{Binding Text,ElementName=TextBox1}" </i:EventTrigger TextBox>
viewmodel:
BehavIoUrCommand = string>
- (p) =>
- CommandResult = string.Format("执行TextChanged命令,触发命令的TextBox值为{0}",p);
- (p) =>
- {
- return !string.IsNullOrEmpty(p);
- }
- );
- ...
- }
这样就可以间接的将TextBox的MouseRightButtonDown事件绑定到Command。
这种方式相当于将事件映射到Command,CanExecute的返回值只能决定命令是否会被执行,而不能是使得命令目标的可用状态发生改变。以上示例中,输入第一个字母时,命令并没有执行,此时命令无效,但文本框仍然有效,输入第二个字母命令才执行
四、使用MvvmLight行为EventToCommand绑定命令
虽然InvokeCommandAction行为可以将控件的事件转换到Command绑定,也可以通过CommandParameter向viewmodel传递参数,但是对于一些特殊的事件,比如MouseMove,我们需要在事件处理方法中得到鼠标位置信息,使用上面的方式仍不能完成任务;这时我们就需要使用EventToCommand行为,它是MvvmLight封装的行为,要使用行为需要添加galaSoft.MvvmLight.Extras.dll和System.Windows.Interactivity.dll的引用。
同样,在Blend4中打开解决方案,选中要触发事件的控件 ,在资产面板中选择行为,在列表中选择EventToCommand,双击生成行为,然后设置EventName为MouseMove,然后设置Command绑定,同时需要设置PassEventArgsToCommand="True",也就是将事件参数传递给Command,生成的代码如下:
xaml:
Grid Ellipse Fill="AliceBlue" Height="180" stroke="Black" Margin="10,8" i:EventTrigger EventName="MouseMove" galaSoft_MvvmLight_Command:EventToCommand PassEventArgsToCommand="True"
- Command="{Binding MoveMouseCommand}" />
- EllipseTextBlock HorizontalAlignment="Center" Text="带事件参数的命令 (鼠标移动事件)"
- textwrapping="Wrap" Grid.Row="7" d:LayoutOverrides="Height"
- Grid.ColumnSpan="2" VerticalAlignment="Center"
- FontSize="20" FontWeight="Bold"
- IsHitTestVisible="False" >
viewmodel:
MoveMouseCommand = new RelayCommand<MouseEventArgs>
- (
- (e) =>
- var element = e.OriginalSource as UIElement;
- var point = e.GetPosition(element);
- CommandResult = string.Format("执行带MouseEventArgs事件参数的命令,鼠标位置:X-{0},Y-{1}",point.X,point.Y);
- }
- );
这里命令的初始化方式与带参数的命令一样,只需将参数类型换成事件参数类型
EventToCommand不仅可以用来传递事件参数,他还可以将CanExecute返回值与命令目标的IsEnable属性关联,我们只需将MustToggleIsEnabled的属性设置为True就可以了,示例代码如下:
xaml:
TextBox x:Name="TextBox2" Text="为空时CanExecute为false" Margin="5,0" Width="200" galaSoft_MvvmLight_Command:EventToCommand Command="{Binding BehavIoUrCommand}"
- MustToggleIsEnabled="{Binding IsChecked,ElementName=chkMustToggle}"
- CommandParameter="{Binding Text,ElementName=TextBox2}" CheckBox x:Name="chkMustToggle" IsChecked="False" Content="MustToggleIsEnabled,勾选则TextBox的可用状态与CanExecute返回值关联"/>
五、使用自定义行为绑定命令
如果以上方法都不能满足你的要求,你还可以自定义行为来绑定命令,以下是WPF中自定义行为的代码(SL代码请在文章最后下载示例代码对照阅读):
首先,我们创建一个命令参数类型:
using System;
- using System.Windows;
- namespace MvvmlightCommand.WPF4.TriggerActions
- class Event@R_411_4045@ion<TEventArgsType>
- object Sender { get; set; }
- public TEventArgsType EventArgs { set; }
- object CommandArgument { }
- }
然后创建行为类:
using System.Windows.Interactivity;
- using System.Windows.Input;
- namespace MvvmlightCommand.WPF4.TriggerActions
- class MapEventToCommand : MapEventToCommandBase<EventArgs>
- class MapRoutedEventToCommand : MapEventToCommandBase<RoutedEventArgs>
- abstract class MapEventToCommandBase<TEventArgsType> : TriggerAction<FrameworkElement>
- where TEventArgsType : EventArgs
- static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand),153); background-color:inherit; font-weight:bold">typeof(MapEventToCommandBase<TEventArgsType>),153); background-color:inherit; font-weight:bold">new PropertyMetadata(null, OnCommandPropertyChanged));
- readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter",153); background-color:inherit; font-weight:bold">typeof(object), OnCommandParameterPropertyChanged));
- private void OnCommandParameterPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var invokeCommand = d as MapEventToCommand;
- if (invokeCommand != null)
- {
- invokeCommand.SetValue(CommandParameterProperty, e.NewValue);
- }
- void OnCommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var invokeCommand = d as MapEventToCommand;
- invokeCommand.SetValue(CommandProperty, e.NewValue);
- }
- }
- protected override void Invoke(if (this.Command == var eventInfo = new Event@R_411_4045@ion<TEventArgsType>
- EventArgs = parameter as TEventArgsType,
- Sender = this.Associatedobject,
- CommandArgument = GetValue(CommandParameterProperty)
- };
- this.Command.CanExecute(eventInfo))
- this.Command.Execute(eventInfo);
- public ICommand Command
- get
- return (ICommand)base.GetValue(CommandProperty);
- set
- base.SetValue(CommandProperty, value);
- object CommandParameter
- return base.GetValue(CommandParameterProperty);
- base.SetValue(CommandParameterProperty,248); line-height:18px"> }
编译生成项目,在Blend4中打开解决方案,选中要触发事件的控件 ,在资产面板中选择行为,在列表中选择MapRoutedEventToCommand ,双击生成行为,然后设置EventName为TextChanged,然后设置Command绑定,代码如下:
xaml:
TextBox x:Name="TextBox3" Text="更改文本框的值" Margin="5,0); background-color:inherit; font-weight:bold">my:MapRoutedEventToCommand Command="{Binding CustomBehaviorCommand}" CommandParameter="P1"copy
CustomBehaviorCommand = new RelayCommand<Event@R_411_4045@ion<RoutedEventArgs>>
- (
- (ei) =>
- {
- Event@R_411_4045@ion<RoutedEventArgs> eventInfo = ei as Event@R_411_4045@ion<RoutedEventArgs>;
- System.Windows.Controls.TextBox sender = eventInfo.Sender as System.Windows.Controls.TextBox;
- CommandResult = string.Format("执行{0}的TextChanged命令,文本框的值:{1},传递的参数:{2},事件参数:{3}",248); line-height:18px"> sender.Name,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px"> sender.Text,
- ei.CommandArgument,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px"> ei.EventArgs.GetType().ToString());
- },108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px"> true;
- }
- );
这样,我们就可以同时将sender、CommandParameter、和事件参数传递到Command的参数中了
本章节主要介绍MvvmLight中命令和事件的处理方法,下章我们将介绍MvvmLight中的Messenger的使用方法,以下是本章源代码下载:
http://download.csdn.net/source/3262832
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。