2009-06-18 5 views
10

W poniższym kodzie, , gdy użytkownik wybierze Klienta w combobox, nazwa klienta zostanie wyświetlona w polu tekstowym pod numerem. Wypełniam pole Combox właściwością ObservableCollection na moim ViewModelu, ale jak mam obsłużyć zdarzenie SelectedItem w moim ViewModelu?Jaki jest najprostszy sposób obsługi zdarzenia SelectedItem z MVVM?

Łatwo to zaimplementować z kodem z tyłu, jak pokazano poniżej, ale jak to zrobić z wzorcem MVVM?

Obecnie mam DelegateCommand i AttachedBehaviors w moim podstawowego szablonu MVVM, że mogę wykorzystać, ale nie mogę dowiedzieć się, jak dostać się je do ognia, gdy „combobox wybiera nowy element”.

Widok:

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

Odpowiedz

12

Powinieneś być w stanie związać się właściwość ViewModel do nieruchomości selectedItem z combobox. Jeśli ustawisz to jako bindowanie dwukierunkowe, otrzymasz powiadomienie, gdy SelectedItem zostanie zmieniony, ponieważ wywoła ustawioną metodę dla właściwości.

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

dokładnie czego szukałem, nie wiedziałem, że to takie proste, dzięki –

+1

Pamiętaj tylko, że to uzależnia twój V/VM ... Jeśli przetestujesz ten kod bez widok, aktualnieSelectedCustomer nigdy nie aktualizuje! Jeśli używasz CollectionView ... To zadziała, nawet jeśli twój widok nie przywróci VM! – rudigrobler

+3

Ogólnie rzecz biorąc zgadzam się, że istnieją zalety CollectionView (chociaż są pewne zastrzeżenia, gdy chcesz powiązać tę samą listę z wieloma selektorami), ale nie sądzę, że twój komentarz jest poprawny. Nie ma więcej zależności w mojej wersji niż twoja, na przykład jeśli chciałem napisać test, aby sprawdzić, czy właściwość LastName jest aktualizowana poprawnie, nie potrzebuję widoku, mogę tylko ustawić właściwość SelectedCustomer poprzez kod testowy. –

10

Wystarczy popatrzeć na this aplikacji na www.codeproject.com. Tutaj używam CollectionView wykryć aktualnie wybranego elementu

Aktualizacja

Korzystanie CollectionView wykryć aktualnie wybrany artykuł

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

Wystarczy pamiętać, aby także ustawić IsSynchronizedWithCurrentItem = "True"

+0

+1 za wymienienie potrzeby 'IsSynchronizedWithCurrentItem =" True "'. Po godzinie próbowania odkrycia, dlaczego 'CurrendChanged' nigdy nie został zwolniony w moim kodzie, uratowałeś ten dzień. – HolySamosa