2011-01-07 14 views
8

Tôi đang cố gắng sử dụng hành vi được đính kèm để thực thi lệnh trong ViewModel của tôi khi người dùng nhấp đúp vào mục danh sách.Hành vi được đính kèm để thực hiện lệnh cho ListViewItem

Tôi đã xem xét một số bài viết về chủ đề và đã thử tạo một ứng dụng thử nghiệm đơn giản nhưng vẫn gặp sự cố, ví dụ: Firing a double click event from a WPF ListView item using MVVM

ViewModel thử nghiệm đơn giản của tôi có 2 bộ sưu tập, một trong đó trả về một danh sách các chuỗi và người kia trả về một danh sách các loại ListViewItem

public class ViewModel 
{ 
    public ViewModel() 
    { 
     Stuff = new ObservableCollection<ListViewItem> 
        { 
         new ListViewItem { Content = "item 1" }, 
         new ListViewItem { Content = "item 2" } 
        }; 

     StringStuff = new ObservableCollection<string> { "item 1", "item 2" }; 
    } 

    public ObservableCollection<ListViewItem> Stuff { get; set; } 

    public ObservableCollection<string> StringStuff { get; set; } 

    public ICommand Foo 
    { 
     get 
     { 
      return new DelegateCommand(this.DoSomeAction); 
     } 
    } 

    private void DoSomeAction() 
    { 
     MessageBox.Show("Command Triggered"); 
    } 
} 

Dưới đây là tài sản gắn liền mà là giống như có thể ví dụ khác mà bạn xem:

public class ClickBehavior 
{ 
    public static DependencyProperty DoubleClickCommandProperty = DependencyProperty.RegisterAttached("DoubleClick", 
       typeof(ICommand), 
       typeof(ClickBehavior), 
       new FrameworkPropertyMetadata(null, new PropertyChangedCallback(ClickBehavior.DoubleClickChanged))); 

    public static void SetDoubleClick(DependencyObject target, ICommand value) 
    { 
     target.SetValue(ClickBehavior.DoubleClickCommandProperty, value); 
    } 

    public static ICommand GetDoubleClick(DependencyObject target) 
    { 
     return (ICommand)target.GetValue(DoubleClickCommandProperty); 
    } 

    private static void DoubleClickChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) 
    { 
     ListViewItem element = target as ListViewItem; 
     if (element != null) 
     { 
      if ((e.NewValue != null) && (e.OldValue == null)) 
      { 
       element.MouseDoubleClick += element_MouseDoubleClick; 
      } 
      else if ((e.NewValue == null) && (e.OldValue != null)) 
      { 
       element.MouseDoubleClick -= element_MouseDoubleClick; 
      } 
     } 
    } 

    static void element_MouseDoubleClick(object sender, MouseButtonEventArgs e) 
    { 
     UIElement element = (UIElement)sender; 
     ICommand command = (ICommand)element.GetValue(ClickBehavior.DoubleClickCommandProperty); 
     command.Execute(null); 
    } 
} 

Trong cửa sổ chính của tôi, tôi đã xác định phong cách mà bộ hành vi gắn liền và liên kết với các lệnh Foo

<Window.Resources> 
    <Style x:Key="listViewItemStyle" TargetType="{x:Type ListViewItem}"> 
     <Setter Property="local:ClickBehavior.DoubleClick" Value="{Binding Foo}"/>     
    </Style> 
</Window.Resources> 

Hoạt động tốt khi ListViewItems được định nghĩa:

<!-- Works --> 
<Label Grid.Row="2" Content="DoubleClick click behaviour:"/>   
<ListView Grid.Row="2" Grid.Column="1" ItemContainerStyle="{StaticResource listViewItemStyle}"> 
    <ListViewItem Content="Item 3" /> 
    <ListViewItem Content="Item 4" /> 
</ListView> 

này hoạt động quá, khi bị ràng buộc vào danh sách các loại ListViewItem:

<!-- Works when items bound are of type ListViewItem --> 
<Label Grid.Row="3" Content="DoubleClick when bound to ListViewItem:"/>   
    <ListView Grid.Row="3" Grid.Column="1" ItemContainerStyle="{StaticResource listViewItemStyle}" ItemsSource="{Binding Stuff}">   
</ListView> 

Nhưng điều này không:

<!-- Does not work when items bound are not ListViewItem --> 
<Label Grid.Row="4" Content="DoubleClick when bound to string list:"/> 
    <ListView Grid.Row="4" Grid.Column="1" ItemContainerStyle="{StaticResource listViewItemStyle}" ItemsSource="{Binding StringStuff}"> 
</ListView> 

Trong cửa sổ đầu ra bạn thấy lỗi, nhưng việc tìm kiếm nó khó hiểu những gì sai.
Lỗi System.Windows.Data: 39: Lỗi đường dẫn BindingExpression: 'Không tìm thấy thuộc tính' Foo 'trên' đối tượng '' 'Chuỗi' (HashCode = 785742638) '. BindingExpression: Đường dẫn = Foo; DataItem = 'Chuỗi' (HashCode = 785742638); phần tử đích là 'ListViewItem' (Tên = ''); thuộc tính mục tiêu là 'DoubleClick' (loại 'ICommand')

Vì vậy, quesion của tôi là: Làm thế nào bạn có thể nhận được lệnh có dây đúng cho mỗi ListViewItem khi bạn ràng buộc ListView của bạn vào danh sách các đối tượng Mô hình?

Cảm ơn.

+0

này rất hữu ích! Để thêm khả năng sử dụng lại, tôi đã thay đổi phần tử ListViewItem = target thành ListViewItem; để Kiểm soát phần tử = mục tiêu dưới dạng Kiểm soát; –

Trả lời

8

Vấn đề là DataContext cho số Binding là chuỗi. Vì không có thuộc tính Foo thuộc lớp chuỗi, bạn đang gặp lỗi. Điều này không xảy ra trong các trường hợp khác vì chúng kế thừa DataContext của chúng từ cha mẹ (điều này không xảy ra đối với các vùng chứa được tạo tự động cho các mục dữ liệu - DataContext là mục dữ liệu).

Nếu bạn thay đổi ràng buộc của bạn để sử dụng các mẹ ListView 's DataContext, nó sẽ làm việc tốt:

Value="{Binding DataContext.Foo, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}" 
+0

Cảm ơn câu trả lời nhanh chóng, Abe. Bạn là một ngôi sao, đã cố gắng tìm ra điều này quá lâu. –

+1

Không vấn đề gì Paul. Các lỗi ràng buộc thực sự khó hiểu, và đôi khi nó chỉ cần một đôi mắt mới để xem những gì đang xảy ra! –

Các vấn đề liên quan