2009-06-18 12 views
10

En el código siguiente, cuando el usuario selecciona Cliente en el cuadro combinado, el nombre del cliente se muestra en un cuadro de texto. Lleno el cuadro de Combox con una propiedad ObservableCollection en mi ViewModel, pero ¿cómo manejo el evento SelectedItem en mi ViewModel?¿Cuál es la forma más fácil de manejar el evento SelectedItem con MVVM?

Es fácil implementar esto con código subyacente como se muestra a continuación, pero ¿cómo hago esto con el patrón MVVM?

Actualmente tengo DelegateCommand y AttachedBehaviors en mi plantilla MVVM básica que puedo usar, pero no puedo encontrar la manera de conseguir que se disparan cuando "cuadro combinado selecciona un nuevo elemento".

Vista:

<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> 

código subyacente:

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); 
} 

Respuesta

12

usted debería ser capaz de unirse a una propiedad en que modelo de vista de la propiedad SelectedItem del cuadro combinado. Si configura esto como enlace bidireccional, se le notificará cuando se modifique SelectedItem porque activará el método set en la propiedad.

modelo de vista:

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> 
+0

exactamente lo que estaba buscando, no sabía que era tan simple, gracias –

+1

Solo recuerde que esto pone una dependencia entre su V/VM ... Si prueba este código sin la vista, ¡el cliente actualmente seleccionado nunca se actualizará! Si usa CollectionView ... ¡Funcionará incluso si su vista no vincula a la VM! – rudigrobler

+3

En general, estoy de acuerdo en que hay ventajas en un CollectionView (aunque hay ciertas condiciones para vincular la misma lista a varios selectores), pero no creo que su comentario sea correcto. No hay más dependencia en mi versión que la suya, por ejemplo, si quería escribir una prueba para verificar que la propiedad LastName se actualiza correctamente, no necesito una vista, solo puedo configurar la propiedad SelectedCustomer a través del código de prueba. –

10

Eche un vistazo a this aplicación en www.codeproject.com. Aquí utilizo el CollectionView para detectar el elemento seleccionado actualmente

actualización

Usando CollectionView para detectar elemento seleccionado actual

ListCollectionView view = (ListCollectionView)CollectionViewSource.GetDefaultView(Customers); 
view.CurrentChanged += delegate 
{ 
    SelectedCustomer= (Customer)view.CurrentItem; 
}; 

Sólo recuerde también configurar IsSynchronizedWithCurrentItem = "true"

+0

+1 por mencionar la necesidad de 'IsSynchronizedWithCurrentItem =" True "'. Después de una hora de tratar de descubrir por qué 'CurrendChanged' nunca se disparó en mi código, has guardado el día. – HolySamosa

Cuestiones relacionadas