2009-06-18 9 views
10

Trong mã bên dưới, khi người dùng chọn Khách hàng trong hộp tổ hợp, tên của khách hàng được hiển thị trong hộp văn bản. Tôi điền vào hộp Combox với một thuộc tính ObservableCollection trên ViewModel của tôi nhưng làm thế nào để xử lý sự kiện SelectedItem trong ViewModel của tôi?Cách dễ nhất để xử lý sự kiện SelectedItem với MVVM là gì?

Thật dễ dàng để thực hiện điều này với mã sau như được hiển thị bên dưới, nhưng làm cách nào để làm điều này với mẫu MVVM?

Tôi hiện đang có DelegateCommandAttachedBehaviors trong mẫu MVVM cơ bản của tôi mà tôi có thể sử dụng, nhưng tôi không thể tìm ra cách để có được chúng để bắn khi "combobox chọn một mục mới".

Xem:

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

Mã Đằng sau:

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

Trả lời

12

Bạn sẽ có thể để ràng buộc một tài sản trong bạn ViewModel đến tài sản SelectedItem của combobox. Nếu bạn thiết lập này như là hai cách ràng buộc, bạn sẽ được thông báo khi SelectedItem được thay đổi bởi vì nó sẽ kích hoạt phương thức set trên thuộc tính.

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

chính xác những gì tôi đang tìm kiếm, không biết nó đơn giản như vậy, cảm ơn –

+1

Chỉ cần nhớ rằng điều này đặt một sự phụ thuộc giữa V/VM của bạn ... Nếu bạn kiểm tra mã này mà không chế độ xem, người dùng CurrentlySelectedCustomer sẽ không bao giờ cập nhật! Nếu bạn sử dụng CollectionView ... Nó sẽ hoạt động ngay cả khi chế độ xem của bạn không ràng buộc với VM! – rudigrobler

+3

Nói chung tôi đồng ý có lợi thế cho một CollectionView (mặc dù có một số điều kiện khi bạn muốn ràng buộc cùng một danh sách với nhiều bộ chọn), nhưng tôi không nghĩ rằng bình luận của bạn là chính xác. Không có sự phụ thuộc nhiều hơn trong phiên bản của tôi, ví dụ nếu tôi muốn viết một bài kiểm tra để kiểm tra xem thuộc tính LastName có cập nhật chính xác không, tôi chỉ cần thiết lập thuộc tính SelectedCustomer thông qua mã kiểm thử. –

10

Có một cái nhìn tại this ứng dụng trên www.codeproject.com. Ở đây tôi sử dụng CollectionView để phát hiện các mục đang được chọn

Cập nhật

Sử dụng CollectionView để phát hiện hiện mục được chọn

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

Chỉ cần nhớ cũng để thiết IsSynchronizedWithCurrentItem = "True"

+0

+1 để đề cập đến sự cần thiết của 'IsSynchronizedWithCurrentItem =" True "'. Sau một giờ cố gắng tìm ra lý do tại sao 'CurrendChanged' không bao giờ bị sa thải trong mã của tôi, bạn đã cứu được một ngày. – HolySamosa