Bind event in WPF custom control for command in ViewModel

I have a custom control that has an event. I have a window using this custom control. The window is bound to the viewmodel. I would like an event from a custom control to be directly connected to the ICommand on my viewmodel. I'm obviously tight here as I can't figure out how to do this. Any help is appreciated.

thanks

+2


a source to share


2 answers


If you want to route an event to a command, you can use the attached property. I used this example to add command support to the ComboBox SelectionChanged event:

http://blog.fossmo.net/post/How-to-create-an-attached-property-in-WPF-using-a-ComboBox.aspx



Greetings.

-1


a source


If it's a one-off, you can use a simple event handler:

<some:CustomControl SuperDuper="OnSuperDuper" />

      

with code for

private void OnSuperDuper(object sender, EventArgs e)
{
  _theCommand.Execute(null, (IInputElement)sender);
}

      

If you want to do this multiple times for a specific event, I would use the attached property.

<some:CustomControl my:AttachedEvents.SuperDuperCommand="{Binding TheCommand}" />

      

where the attached property is just:

// use propa snippet to build this quickly
public static ICommand GetSuperDuperCommand(DependencyObject obj) { return (ICommand)obj.GetValue(SuperDuperCommandProperty); }
public static void SetSuperDuperCommand(DependencyObject obj, ICommand value) { obj.SetValue(SuperDuperCommandProperty, value); }
public static readonly DependencyProperty SuperDuperCommandProperty = DependencyProperty.RegisterAttached("SuperDuperCommand", typeof(ICommand), typeof(AttachedEvents), new PropertyMetadata
{
  PropertyChangedCallback = (obj, e) =>
  {
    if(oldCommand==null) ((CustomControl)obj).SuperDuper += OnSuperDuper;
    if(newCommand==null) ((CustomControl)obj).SuperDuper -= OnSuperDuper;
  }
});

private void OnSuperDuper(object sender, EventArgs e)
{
  var control = (CustomControl)sender;
  GetSuperDuperCommand(sender).Execute(null, sender));
}

      



You might be able to generalize this to map any event to any command using MarkupExtension. Here's the idea:

<some:CustomControl SuperDuper="{lib:CommandWrapper {Binding TheCommand}}" />

      

The code looks like this:

public class CommandWrapper : MarkupExtension
{
  public BindingBase CommandBinding { get; set; }

  public CommandWrapper() {}
  public CommandWrapper(BindingBase commandBinding) { CommandBinding = commandBinding; }

  public object ProvideValue(IServiceProvider serviceProvider)
  {
    return new EventHandler((obj, e) =>
    {
      // Evaluate CommandBinding against obj, fire command
    });
  }
}

      

You can detail the details. Note that instead of simply specifying "new EventHandler", you can pass the actual type of the event handler to the CommandWrapper and use reflection to create the appropriate delegate.

I'm not entirely sure if the XAML parser will let you set the event using the MarkupExtension, so this last solution might not work just like that. But if not, it can be combined with the attached property:

<some:CustomControl lib:CommandWrapper.Add="{lib:CommandWrapper SuperDuper,{Binding TheCommand}}" />

      

This will definitely work: CommandWrapper.Add will get the event name from the CommandWrapper generated by the markup extension and can create a matching mapping.

+2


a source







All Articles