微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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" VerticalAlignment="Top" Width="107" Command="{Binding Main.noparamCommand,Mode=OneWay}"/>
也可用行为模式绑定(最好在Blend中设计)
teraction.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 Event@R_505_4045@ion<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),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 Event@R_505_4045@ion<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<Event@R_505_4045@ion<RoutedEventArgs>>(ShowEventParamMessage);
         
        }

public RelayCommand<Event@R_505_4045@ion<RoutedEventArgs>> EventParamCommand
        {
            get;
            private set;
        }
        private void ShowEventParamMessage(Event@R_505_4045@ion<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" 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<Event@R_505_4045@ion<RoutedEventArgs>>(ShowEventParamMessage);
         
        }
可以将CanExcute绑定到一个控件上来控制事件是否执行,只要该属性发生变化都将触发RaiseCanExecuteChanged,RaiseCanExecuteChanged会根据canExcute参数值觉得是否可执行,有点类似于控件的Enable,但其应用范围可考虑在实际项目中有条件触发。 以上是RelayCommand的应用,相对比较简单,在MVVM light toolkits 中还有Message没开始学习,都连续几天没好好睡觉了,累死了!!!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐