Home > C#, WinRT > How to bind the ItemClick event to a Command and pass the clicked item to it

How to bind the ItemClick event to a Command and pass the clicked item to it

07/03/2013

The ItemClick event of GridView and ListView in WinRT contain an ItemClickEventArgs argument that allows us to retrieve the clicked item. These controls don’t expose a Command property that can be binded to a property in a ViewModel. So, if you want to follow an MVVM approach and we need to execute a command when an item is clicked, we have two alternatives.

First, we can use WinRTTriggers, an open source library available on CodePlex that adds the support for triggers in Windows Store apps. With that, we can write something like this:

<GridView 
    x:Name="itemGridView" 
    ...>

    <triggers:Interactions.Triggers> 
        <triggers:EventTrigger EventName="ItemClick"> 
            <triggers:InvokeCommandAction Command="{Binding MyItemClickCommand}" 
                                          PassEventArgsToCommand="True" /> 
        </triggers:EventTrigger> 
    </triggers:Interactions.Triggers>

</GridView>

In this way, when the ItemClick event is raised, the MyItemClickCommand command is automatically invoked. With the PassEventArgsToCommand parameter set to true, the ItemClickEventArgs is passed as an argument to the command, so that we can read its ClickedItem property to access the item that has been clicked.

However, I don’t like very much this solution, because we’re passing to the ViewModel an object that belongs to the Windows.UI.Xaml.Controls, and moreover we need to manually cast the ClickedItem property to the real object.

So, it this case I prefer to follow another approach. I have created a class that defines an attached property:

public static class ItemClickCommand 
{ 
    public static readonly DependencyProperty CommandProperty = 
        DependencyProperty.RegisterAttached("Command", typeof(ICommand), 
        typeof(ItemClickCommand), new PropertyMetadata(null, OnCommandPropertyChanged));

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

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

    private static void OnCommandPropertyChanged(DependencyObject d, 
        DependencyPropertyChangedEventArgs e) 
    { 
        var control = d as ListViewBase; 
        if (control != null) 
            control.ItemClick += OnItemClick; 
    }

    private static void OnItemClick(object sender, ItemClickEventArgs e) 
    { 
        var control = sender as ListViewBase; 
        var command = GetCommand(control);

        if (command != null && command.CanExecute(e.ClickedItem)) 
            command.Execute(e.ClickedItem); 
    } 
}

Using this class, when the ItemClick event is raised, the ICommand that has been assigned to the Command attached property is executed, passing the real object directly to it. So, we can write something like this:

<GridView 
    x:Name="itemGridView" 
    ... 
    helpers:ItemClickCommand.Command="{Binding MyItemClickCommand}">

And, in our ViewModel, we can define a command that receives the item as argument:

private RelayCommand<MyItem> myItemClickCommand; 
public RelayCommand<MyItem> MyItemClickCommand 
{ 
    get 
    { 
        if (myItemClickCommand == null) 
        { 
            myItemClickCommand = new RelayCommand<MyItem>( 
                (item) => 
                {                            
                    // ... 
                }); 
        }

        return myItemClickCommand; 
    } 
}

Note that, as we’re using ListViewBase in ItemClickCommand class, this attached property works with both GridView and ListView.

Categories: C#, WinRT
  1. 08/03/2013 at 17:48

    Thanks. You made my day. This is exactly the solution i needed🙂

    • 08/03/2013 at 17:50

      You’re welcome. I’m happy I have helped you🙂

      • 08/03/2013 at 18:15

        Oh yes, you had🙂
        I played a lot with MetroEventToCommand. It’s a nice package but i had no chance to pass the ItemClick arguments to the command.

  1. 08/03/2013 at 12:38
Comments are closed.
%d bloggers like this: