Skip to content

Instantly share code, notes, and snippets.

@wi7a1ian
Created September 24, 2019 20:49
InvokeCommandAction vs EventToCommand #wpf #csharp
public class EventCommandExecuter : TriggerAction<DependencyObject>
{
public EventCommandExecuter()
: this(CultureInfo.CurrentCulture)
{
}
public EventCommandExecuter(CultureInfo culture)
{
Culture = culture;
}
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand), typeof(EventCommandExecuter), new PropertyMetadata(null));
public object EventArgsConverterParameter
{
get { return (object)GetValue(EventArgsConverterParameterProperty); }
set { SetValue(EventArgsConverterParameterProperty, value); }
}
public static readonly DependencyProperty EventArgsConverterParameterProperty =
DependencyProperty.Register("EventArgsConverterParameter", typeof(object), typeof(EventCommandExecuter), new PropertyMetadata(null));
public IValueConverter EventArgsConverter { get; set; }
public CultureInfo Culture { get; set; }
protected override void Invoke(object parameter)
{
var cmd = Command;
if (cmd != null)
{
var param = parameter;
if (EventArgsConverter != null)
{
param = EventArgsConverter.Convert(parameter, typeof(object), EventArgsConverterParameter, CultureInfo.InvariantCulture);
}
if (cmd.CanExecute(param))
{
cmd.Execute(param);
}
}
}
}
<UserControl ...
xmlns:cmd="clr-namespace:MyProject.WPF.Commands"
xmlns:c="clr-namespace:MyProject.WPF.Converters"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity">
<TextBlock ...>
<i:Interaction.Behaviors>
<cmd:EventCommandExecuter Command="{Binding Path=Update, Mode=OneTime}" EventArgsConverter="{x:Static c:SomethingToSomethingConverter}"/>
<!--<cmd:EventCommandExecuter
Command="{Binding Path=Update, Mode=OneTime}"
EventArgsConverter="{x:Static c:SomethingToSomethingConverter}"
EventArgsConverterParameter="{Binding ElementName=SomeEventSource, Mode=OneTime}"/>-->
</i:Interaction.Behaviors>
</TextBlock>
</UserControl>
<UserControl ...
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
<TextBlock ...>
<i:Interaction.Behaviors>
<beh:EventToCommandBehavior Command="{Binding SomeCommand}" Event="MouseDown" PassArguments="True" />
</i:Interaction.Behaviors>
</TextBlock>
</UserControl>
public class EventToCommandBehavior : Behavior<FrameworkElement>
{
private Delegate _handler;
private EventInfo _oldEvent;
public string Event { get { return (string)GetValue(EventProperty); } set { SetValue(EventProperty, value); } }
public static readonly DependencyProperty EventProperty = DependencyProperty.Register("Event", typeof(string), typeof(EventToCommandBehavior), new PropertyMetadata(null, OnEventChanged));
public ICommand Command { get { return (ICommand)GetValue(CommandProperty); } set { SetValue(CommandProperty, value); } }
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(EventToCommandBehavior), new PropertyMetadata(null));
public bool PassArguments { get { return (bool)GetValue(PassArgumentsProperty); } set { SetValue(PassArgumentsProperty, value); } }
public static readonly DependencyProperty PassArgumentsProperty = DependencyProperty.Register("PassArguments", typeof(bool), typeof(EventToCommandBehavior), new PropertyMetadata(false));
private static void OnEventChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var beh = (EventToCommandBehavior)d;
if (beh.AssociatedObject != null) // is not yet attached at initial load
beh.AttachHandler((string)e.NewValue);
}
protected override void OnAttached()
{
AttachHandler(this.Event);
}
private void AttachHandler(string eventName)
{
if (_oldEvent != null)
_oldEvent.RemoveEventHandler(this.AssociatedObject, _handler);
if (!string.IsNullOrEmpty(eventName))
{
EventInfo ei = this.AssociatedObject.GetType().GetEvent(eventName);
if (ei != null)
{
MethodInfo mi = this.GetType().GetMethod("ExecuteCommand", BindingFlags.Instance | BindingFlags.NonPublic);
_handler = Delegate.CreateDelegate(ei.EventHandlerType, this, mi);
ei.AddEventHandler(this.AssociatedObject, _handler);
_oldEvent = ei;
}
else
throw new ArgumentException(string.Format("The event '{0}' was not found on type '{1}'", eventName, this.AssociatedObject.GetType().Name));
}
}
private void ExecuteCommand(object sender, EventArgs e)
{
object parameter = this.PassArguments ? e : null;
if (this.Command != null)
{
if (this.Command.CanExecute(parameter))
this.Command.Execute(parameter);
}
}
}
<UserControl ...
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
<TextBlock ...>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<i:InvokeCommandAction Command="{Binding Path=SomeCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</UserControl>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment