silverlight 学习笔记 (五): MVVM Light Toolkits 之 RealCommand

在MVVM模式中我们在设计ViewModel时需要定义大量的事件处理程序,这些事件处理程序可以通过在View中绑定进行触发,具体时间参考前面所讲。ViewModel中的需要将事件定义为公开的继承ICammand的属性如下:

public ICommand QueryCommand { get; private set; }

ICommand接口提供了两个方法(Execute、CanExecute)和一个事件(CanExecuteChanged),Execute执行事件实际的处理函数,CanExecute表示是否执行事件,CanExecuteChanged事件则是通知CanExecute状态的改变。

在MVVM light toolkits 包中一个很重要的功能就是提供了对ICommand的封装,让我们在实现ViewModel中的事件处理变动更方便了,下面重点说下RelayCommand方法的应用。

1、如何在ViewModel中触发一个不带任何参数的事件

首先在ViewModel中定义一个事件属性,并在构造函数中定义为该事件指定处理函数。然后在View中通过绑定ViewModel的事件属性,这样就能够实现对事件的触发了。需要说明的是在silverlight中只有实现了ICommandSource的控件才能实现Command的绑定,否则可以通过Silverlight中行为模式(InvokeCommandAction)进行触发。

public MainViewModel()//构造函数 { NoParamCommand=new RelayCommand(ShowMessage); CanExecuteCommand= new RelayCommand(ShowMessage, () => CanExcute); } public RelayCommand NoParamCommand { get; private set; }private void ShowMessage() { MessageBox.Show("this is test "); }View中的按钮事件绑定
<Button Content="NoParamMessage" HorizontalAlignment="Left" Height="26" Margin="43,56,0,0" VerticalAlignment="Top" Width="107" Command="{Binding Main.NoParamCommand, Mode=OneWay}"/>也可用行为模式绑定(最好在Blend中设计)
<Button Content="NoParamMessage" HorizontalAlignment="Left" Height="26" Margin="43,56,0,0" VerticalAlignment="Top" Width="107"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <i:InvokeCommandAction Command="{Binding Main.NoParamCommand, Mode=OneWay}"/> </i:EventTrigger> </i:Interaction.Triggers> </Button>

2、如何触发一个带参数的事件

方法基本同上,不同的是需要在事件属性使用一个带参数的泛型定义

public RelayCommand<string> ParamCommand { get; private set; } public MainViewModel() { NoParamCommand=new RelayCommand(ShowMessage); CanExecuteCommand= new RelayCommand(ShowMessage, () => CanExcute); ParamCommand=new RelayCommand<string>(ShowParamMessage); } private void ShowParamMessage(string msg) { MessageBox.Show(msg); }

3、如何在事件处理函数上携带事件源及事件源参数,比如我们一个TextBox控件在TextChanged事件

private void textBox1_TextChanged(object sender, TextChangedEventArgs e) { }我们希望在ViewModel中定义的事件处理函数能够携带 sender和事件参数 e,这样做在实际项目中还是有很大意义的。这就需要使用自定义事件了,本人从网上找到一段代码
public class EventInformation<TEventArgsType> { public object Sender { get; set; } public TEventArgsType EventArgs { get; set; } public object CommandArgument { get; set; } } public class MapEventToCommand : MapEventToCommandBase<EventArgs> { } public class MapRoutedEventToCommand : MapEventToCommandBase<RoutedEventArgs> { } public abstract class MapEventToCommandBase<TEventArgsType> : TriggerAction<FrameworkElement> where TEventArgsType : EventArgs { public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(MapEventToCommandBase<TEventArgsType>), new PropertyMetadata(null, OnCommandPropertyChanged)); public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(MapEventToCommandBase<TEventArgsType>), new PropertyMetadata(null, OnCommandParameterPropertyChanged)); private static void OnCommandParameterPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var invokeCommand = d as MapEventToCommand; if (invokeCommand != null) { invokeCommand.SetValue(CommandParameterProperty, e.NewValue); } } private static void OnCommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var invokeCommand = d as MapEventToCommand; if (invokeCommand != null) { invokeCommand.SetValue(CommandProperty, e.NewValue); } } protected override void Invoke(object parameter) { if (this.Command == null) { return; } var eventInfo = new EventInformation<TEventArgsType> { EventArgs = parameter as TEventArgsType, Sender = this.AssociatedObject, CommandArgument = GetValue(CommandParameterProperty) }; if (this.Command.CanExecute(eventInfo)) { this.Command.Execute(eventInfo); } } public ICommand Command { get { return (ICommand)base.GetValue(CommandProperty); } set { base.SetValue(CommandProperty, value); } } public object CommandParameter { get { return base.GetValue(CommandParameterProperty); } set { base.SetValue(CommandParameterProperty, value); } } }
该事件的使用方法
public MainViewModel() { NoParamCommand=new RelayCommand(ShowMessage); CanExecuteCommand= new RelayCommand(ShowMessage, () => CanExcute); ParamCommand=new RelayCommand<string>(ShowParamMessage); EventParamCommand = new RelayCommand<EventInformation<RoutedEventArgs>>(ShowEventParamMessage); }
public RelayCommand<EventInformation<RoutedEventArgs>> EventParamCommand { get; private set; } private void ShowEventParamMessage(EventInformation<RoutedEventArgs> ei) { string msg = ""; msg += "事件源:" + (ei.Sender as TextBox).Text; msg += "事件参数:" + ei.EventArgs.GetType().ToString(); msg += "绑定参数:" + ei.CommandArgument.ToString(); MessageBox.Show(msg); }View中的绑定使用的是一样自定义的行为
<TextBox Height="23" HorizontalAlignment="Left" Margin="166,174,0,0" x:Name="textBox1" VerticalAlignment="Top" Width="120" > <i:Interaction.Triggers> <i:EventTrigger EventName="TextChanged"> <MvvmLight3_ViewModel:MapRoutedEventToCommand Command="{Binding Main.EventParamCommand, Mode=OneWay}" CommandParameter="{Binding Text, ElementName=textBox}"/> </i:EventTrigger> </i:Interaction.Triggers> </TextBox>
4、如何有条件定义事件执行或不执行
其实很简单,ICommand有一个参数canExcute,只需要对该参数进行设置即可,需要注意的是该参数设置后要触发一个事件RaiseCanExecuteChanged
 private bool _canExcute=false; public bool CanExcute { get { return _canExcute; } set { _canExcute = value; RaisePropertyChanged("CanExcute"); CanExecuteCommand.RaiseCanExecuteChanged(); } } public RelayCommand CanExecuteCommand { get; private set; } public MainViewModel() { NoParamCommand=new RelayCommand(ShowMessage); CanExecuteCommand= new RelayCommand(ShowMessage, () => CanExcute); ParamCommand=new RelayCommand<string>(ShowParamMessage); EventParamCommand = new RelayCommand<EventInformation<RoutedEventArgs>>(ShowEventParamMessage); }

可以将CanExcute绑定到一个控件上来控制事件是否执行,只要该属性发生变化都将触发RaiseCanExecuteChanged,RaiseCanExecuteChanged会根据canExcute参数值觉得是否可执行,有点类似于控件的Enable,但其应用范围可考虑在实际项目中有条件触发。
以上是RelayCommand的应用,相对比较简单,在MVVM light toolkits 中还有Message没开始学习,都连续几天没好好睡觉了,累死了!!!






转载于:https://www.cnblogs.com/oldkingsir/archive/2011/09/08/2365632.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值