Binding Commands to Events?

Have a look at Marlon Grech's Attached Command Behaviour, it could be exactly what you're looking for


Use System.Windows.Interactivity

…xmlns:i=http://schemas.microsoft.com/expression/2010/interactivity…

<Slider    
    <i:Interaction.Triggers>    
        <i:EventTrigger EventName="ValueChanged">
            <i:InvokeCommandAction    
                Command="{Binding MyCommand}"    
                CommandParameter="{Binding Text, ElementName=textBox}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Slider>

Make sure your project references the assembly System.Windows.Interactivity.

Source: MSDN Blog Executing a command from an event of your choice

[Update] Have a look to to Microsoft.Xaml.Behaviors.Wpf (available since 03.12.2018) Official package by Microsoft.


I implemented it using Attached Properties and Reflection. I cannot say it is the best implementation, but I will maybe improve it and it may be a good start for you.

public class EventBinding : DependencyObject
{
    public static string GetEventName(DependencyObject obj)
    {
        return (string)obj.GetValue(EventNameProperty);
    }

    public static void SetEventName(DependencyObject obj, string value)
    {
        obj.SetValue(EventNameProperty, value);
        var eventInfo = obj.GetType().GetEvent(value);
        var eventHandlerType = eventInfo.EventHandlerType;
        var eventHandlerMethod = typeof(EventBinding).
            GetMethod("EventHandlerMethod", BindingFlags.Static | BindingFlags.NonPublic);
        var eventHandlerParameters = eventHandlerType.GetMethod("Invoke").GetParameters();
        var eventArgsParameterType = eventHandlerParameters.
            Where(p => typeof(EventArgs).IsAssignableFrom(p.ParameterType)).
            Single().ParameterType;
        eventHandlerMethod = eventHandlerMethod.MakeGenericMethod(eventArgsParameterType);
        eventInfo.AddEventHandler(obj, Delegate.CreateDelegate(eventHandlerType, eventHandlerMethod));
    }

    private static void EventHandlerMethod<TEventArgs>(object sender, TEventArgs e)
        where TEventArgs : EventArgs
    {
        var command = GetCommand(sender as DependencyObject);
        command.Execute(new EventInfo<TEventArgs>(sender, e));
    }

    public static readonly DependencyProperty EventNameProperty = 
        DependencyProperty.RegisterAttached("EventName", typeof(string), typeof(EventHandler));

    public static ICommand GetCommand(DependencyObject obj)
    {
        return (ICommand)obj.GetValue(CommandProperty);
    }

    public static void SetCommand(DependencyObject obj, ICommand value)
    {
        obj.SetValue(CommandProperty, value);
    }

    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(EventBinding));

}

public class EventInfo<TEventArgs>
{
    public object Sender { get; set; }
    public TEventArgs EventArgs { get; set; }

    public EventInfo(object sender, TEventArgs e)
    {
        Sender = sender;
        EventArgs = e;
    }
}

public class EventInfo : EventInfo<EventArgs>
{
    public EventInfo(object sender, EventArgs e)
        : base(sender, e) { }
}

public class EventBindingCommand<TEventArgs> : RelayCommand<EventInfo<TEventArgs>>
    where TEventArgs : EventArgs
{
    public EventBindingCommand(EventHandler<TEventArgs> handler)
        : base(info => handler(info.Sender, info.EventArgs)) { }
}

Examples of usage:

View

<DataGrid local:EventBinding.EventName="CellEditEnding"
          local:EventBinding.Command="{Binding CellEditEndingCommand}" />

Model

private EventBindingCommand<DataGridCellEditEndingEventArgs> _cellEditEndingCommand;

public EventBindingCommand<DataGridCellEditEndingEventArgs> CellEditEndingCommand
{
    get 
    { 
        return _cellEditEndingCommand ?? (
            _cellEditEndingCommand = new EventBindingCommand<DataGridCellEditEndingEventArgs>(CellEditEndingHandler)); 
    }
}

public void CellEditEndingHandler(object sender, DataGridCellEditEndingEventArgs e)
{
    MessageBox.Show("Test");
}

In order to handle events, you must have some code that attaches itself to the event and executes your command in response. The final goal is to have in XAML:

  MouseMoveCommand="{Binding MyCommand}"

In order to achieve this you need to define an attached property for each event that you want to handle. See this for an example and a framework for doing this.

Tags:

C#

Wpf

Xaml

Mvvm