Silverlight Commands Hacks: Passing EventArgs as CommandParameter to DelegateCommand triggered by Ev
- by brainbox
Today I've tried to find a way how to pass EventArgs as CommandParameter to DelegateCommand triggered by EventTrigger. By reverse engineering of default InvokeCommandAction I find that blend team just ignores event args.To resolve this issue I have created my own action for triggering delegate commands.public sealed class InvokeDelegateCommandAction : TriggerAction<DependencyObject>{ /// <summary> /// /// </summary> public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(InvokeDelegateCommandAction), null); /// <summary> /// /// </summary> public static readonly DependencyProperty CommandProperty = DependencyProperty.Register( "Command", typeof(ICommand), typeof(InvokeDelegateCommandAction), null); /// <summary> /// /// </summary> public static readonly DependencyProperty InvokeParameterProperty = DependencyProperty.Register( "InvokeParameter", typeof(object), typeof(InvokeDelegateCommandAction), null); private string commandName; /// <summary> /// /// </summary> public object InvokeParameter { get { return this.GetValue(InvokeParameterProperty); } set { this.SetValue(InvokeParameterProperty, value); } } /// <summary> /// /// </summary> public ICommand Command { get { return (ICommand)this.GetValue(CommandProperty); } set { this.SetValue(CommandProperty, value); } } /// <summary> /// /// </summary> public string CommandName { get { return this.commandName; } set { if (this.CommandName != value) { this.commandName = value; } } } /// <summary> /// /// </summary> public object CommandParameter { get { return this.GetValue(CommandParameterProperty); } set { this.SetValue(CommandParameterProperty, value); } } /// <summary> /// /// </summary> /// <param name="parameter"></param> protected override void Invoke(object parameter) { this.InvokeParameter = parameter; if (this.AssociatedObject != null) { ICommand command = this.ResolveCommand(); if ((command != null) && command.CanExecute(this.CommandParameter)) { command.Execute(this.CommandParameter); } } } private ICommand ResolveCommand() { ICommand command = null; if (this.Command != null) { return this.Command; } var frameworkElement = this.AssociatedObject as FrameworkElement; if (frameworkElement != null) { object dataContext = frameworkElement.DataContext; if (dataContext != null) { PropertyInfo commandPropertyInfo = dataContext .GetType() .GetProperties(BindingFlags.Public | BindingFlags.Instance) .FirstOrDefault( p => typeof(ICommand).IsAssignableFrom(p.PropertyType) && string.Equals(p.Name, this.CommandName, StringComparison.Ordinal) ); if (commandPropertyInfo != null) { command = (ICommand)commandPropertyInfo.GetValue(dataContext, null); } } } return command; }}Example:<ComboBox> <ComboBoxItem Content="Foo option 1" /> <ComboBoxItem Content="Foo option 2" /> <ComboBoxItem Content="Foo option 3" /> <Interactivity:Interaction.Triggers> <Interactivity:EventTrigger EventName="SelectionChanged" > <Presentation:InvokeDelegateCommandAction Command="{Binding SubmitFormCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=InvokeParameter}" /> </Interactivity:EventTrigger> </Interactivity:Interaction.Triggers> </ComboBox>BTW: InvokeCommanAction CommandName property are trying to find command in properties of view. It very strange, because in MVVM pattern command should be in viewmodel supplied to datacontext.