19 November 2014

MVVM: Binding ListBox item double click event to a command

With intention of having 'no code' in code behind file, we often invest lot of time in finding how to invoke a command in your ViewModel whenever a UIElement raises an event. I certainly invested couple of hours googling.. binging for readymade answers. I couldn't find a satisfactory answers (may be I am poor in using right keywords ). But, with help of couple of posts in sites like StackOverflow & MSDN, I arrived at this very simple approach.

Below is my ViewModel which has a collection called Cities which I will be displaying in a ListBox in my View. My ViewModel has a command called ItemSelectedCommand which should be incoked when user double clicks on city.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/// <summary>
/// ViewModel for CityView
/// </summary>
public class CityViewModel : ViewModelBase
{
    /// <summary>
    /// Command that responds item double click event.
    /// </summary>
    public DelegateCommand ItemSelectedCommand { get; private set; }

    /// <summary>
    /// Gets or sets the selected city.
    /// </summary>
    public string SelectedCity { get; set; }

    /// <summary>
    /// Gets the list of cities.
    /// </summary>
    public List<string> Cities { get; private set; }

    /// <summary>
    /// Initializes new instance of <see cref="CityViewModel"/> class.
    /// </summary>
    public CityViewModel()
    {
        ItemSelectedCommand = new DelegateCommand(OnItemSelected);
        Cities = new List<string>() { "Bangalore", "New York", "Sydney", "London", "Washington" };
    }

    /// <summary>
    /// This method is executed when user double clicks on a city.
    /// </summary>
    /// <param name="sender">Unsed Parameter.</param>
    private void OnItemSelected(object sender)
    {            
        //Do the processing you need
    }
}


And here is the XAML

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<ListBox HorizontalAlignment="Center" ItemsSource="{Binding Cities}" SelectedItem="{Binding SelectedCity}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}">
                <TextBlock.InputBindings>
                    <MouseBinding Gesture="LeftDoubleClick"                                           
                                  Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.ItemSelectedCommand}"/>
                </TextBlock.InputBindings>
            </TextBlock>
        </DataTemplate>
    </ListBox.ItemTemplate>                  
</ListBox>


I hope there is no need to explain the code and I hope you enjoyed reading this :)