Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to trigger ViewModel command for a specific button events

How can a command on a ViewModel be invoked by a specific event of a button, such as MouseDoubleClick?

like image 210
Smaug Avatar asked Jan 02 '13 13:01

Smaug


1 Answers

You can use the EventTrigger in the System.Windows.Interactivity namespace, which is part of the so-called Prism framework. If you're just getting started with MVVM, don't care too much for Prism by now, but keep it in mind for later. Anyway, you can steel the EventTrigger

It works like this:

Reference the assembly System.Windows.Interactivity.dll

In XAML, reference the namespace:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

Then in your Button or any other control, add a EventTrigger like this:

<Button Content="Button">
   <i:Interaction.Triggers>
      <i:EventTrigger EventName="MouseDoubleClick">
         <i:InvokeCommandAction Command="{Binding CommandToBindTo}" 
                                CommandParameter="{Binding CommandParameterToBindTo}" />
      </i:EventTrigger>
   </i:Interaction.Triggers>
</Button>

This way, you bind your event to a Command on your DataContext.

Remark

To clarify the usage, here's a kind of real life example including the ViewModel. The fictional requirement is to allow the user to select an item in a list and then perform a command which takes the selected item as a parameter:

<ListBox x:Name="ItemsList" ItemsSource="{Binding Items}" />

<Button Content="Do something with selected item">
   <i:Interaction.Triggers>
      <i:EventTrigger EventName="MouseDoubleClick">
         <i:InvokeCommandAction Command="{Binding DoSomethingCommand}" 
                                CommandParameter="{Binding SelectedItem, 
                                                   ElementName=ItemsList}" />
      </i:EventTrigger>
   </i:Interaction.Triggers>
</Button>

And that would be the ViewModel. Note how the parameter to the command is used, in the example with a generic version of a DelegateCommand object as you get it in every MVVM framework (sometimes RelayCommand). This class takes the type of the required parameter as a generic parameter (here ItemViewModel) and requires a method which takes an according parameter (here ExecuteDoSomethingWithItem(ItemViewModel ...)). The rest is WPF magic: The oject to which the CommandParameter property is bound in your XAML will be passed through as the parameter in your Execute(...) function.

public class ViewModel
{
    ObservableCollection<ItemViewModel> Items { get; set; }

    public ICommand DoSomethingCommand
    {
        get
        {
            return _doSomethingCommand ??
                   (_doSomethingCommand = new DelegateCommand<ItemViewModel>(ExecuteDoSomethingWithItem));
        }
    }

    private DelegateCommand<ItemViewModel> _doSomethingCommand;

    private void ExecuteDoSomethingWithItem(ItemViewModel itemToDoSomethingWith)
    {
        // Do something
    }

    public ViewModel()
    {
        Items = new ObservableCollection<ItemViewModel>();
        // Fill the collection
    }
}

Have fun with learning MVVM, it's worth it.

like image 94
Marc Avatar answered Oct 30 '22 14:10

Marc