What is the easiest way to handle SelectedItem event with MVVM?

Edward Tanguay picture Edward Tanguay · Jun 18, 2009 · Viewed 17.6k times · Source

In the code below, when user selects Customer in the combobox, the customer's name is displayed in a textbox. I fill the Combox box with an ObservableCollection property on my ViewModel but how do I handle the SelectedItem event in my ViewModel?

It's easy to implement this with code-behind as shown below, but how do I do this with the MVVM pattern?

I currently have DelegateCommand and AttachedBehaviors in my basic MVVM template that I can use, but I can't figure out how to get them to fire when "combobox selects a new item".

View:

<Window.Resources>
    <DataTemplate x:Key="CustomerTemplate">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding LastName}"/>
        </StackPanel>
    </DataTemplate>
</Window.Resources>

<DockPanel LastChildFill="False" Margin="10">
    <ComboBox 
        x:Name="CustomerList"
        ItemTemplate="{StaticResource CustomerTemplate}"
        HorizontalAlignment="Left"
        DockPanel.Dock="Top" 
        Width="200"
        SelectionChanged="CustomerSelected"
        ItemsSource="{Binding Customers}"/>

    <TextBlock x:Name="CurrentlySelectedCustomer"/>
</DockPanel>

Code Behind:

private void CustomerSelected(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
    Customer customer = (Customer)CustomerList.SelectedItem;
    CurrentlySelectedCustomer.Text = String.Format("{0} {1}", customer.FirstName, customer.LastName);
}

Answer

Martin Harris picture Martin Harris · Jun 18, 2009

You should be able to bind a property in you ViewModel to the SelectedItem property of the combobox. If you set this up as two way binding you will be notified when the SelectedItem is changed because it will trigger the set method on the property.

ViewModel:

public ObservableCollection Customers
{
   get { return _customers; }
   set
   {
       if (_customers != value)
       {
           _customers = value;
           OnPropertyChanged("Customers");
       }
   }
}

public Customer SelectedCustomer
{
   get { return _selectedCustomer; }
   set
   {
       if (_selectedCustomer != value)
       {
           _selectedCustomer= value;
           LastName= value.LastName;
           OnPropertyChanged("SelectedCustomer");
       }
   }
}

public Customer LastName
{
   get { return _lastName; }
   set
   {
       if (_lastName!= value)
       {
           _lastName= value;
           OnPropertyChanged("LastName");
       }
   }
}

Xaml:

<DockPanel LastChildFill="False" Margin="10">
    <ComboBox 
        x:Name="CustomerList"
        ItemTemplate="{StaticResource CustomerTemplate}"
        HorizontalAlignment="Left"
        DockPanel.Dock="Top" 
        Width="200"
        SelectedItem="{Binding SelectedCustomer, Mode=TwoWay}"
        ItemsSource="{Binding Customers}"/>

    <TextBlock x:Name="CurrentlySelectedCustomer"
               Text="{Binding LastName}"/>
</DockPanel>