2012-12-24 13 views
18

Tôi có listview và tôi muốn hiển thị cửa sổ mới khi ai đó nhấp đúp vào vị trí bất kỳ. Nhưng tôi có ứng dụng mvvm và tôi không muốn có bất kỳ chức năng trong mã phía sau của tập tin xaml, như thế này: How to bind a Command to double-click on a row in DataGrid và nhiều mẫu khác như thế này. Tôi muốn có phương pháp trong tập tin viewmodel và ràng buộc nó như thế này:Cách liên kết lệnh bấm chuột mousedouble trong mvvm

<ListView ... MouseDoubleClick="{Binding myfunction}"> 

Cảm ơn

+0

Hãy xem [ở đây] (http://stackoverflow.com/questions/4785685/wpf-and-mvvm-binding -events) cho một ví dụ MVVM cho các sự kiện Mouse. –

Trả lời

22

Đây là ví dụ hoạt động của phương pháp kích hoạt lệnh (Trong ViewModel) dựa trên mục được nhấp trong danh sách. Lệnh trong ViewModel sẽ nhận được mục "được nhấp" làm tham số của nó.

Tôi đang sử dụng Textblock.InputBindings và có thể là một phần của Blend SDK được liên kết bởi Blachshma, nhưng bạn sẽ không cần bất kỳ DLL nào khác để hoạt động.

Trong ví dụ của tôi, ViewModel được gắn với DataContext của UserControl, đó là lý do tại sao tôi cần sử dụng RelativeSource FindAncestor để tìm ViewModel từ TextBlock của tôi.

Sửa: Cố định vấn đề chiều rộng bằng cách gắn các Width của TextBlock đến ActualWidth của ListBox.

Chỉ cần một sự cố, nhấp đúp sẽ chỉ hoạt động khi bạn nhấp vào bên trong văn bản trong khối chữ ngay cả khi danh sách đó rộng hơn nhiều.

<ListView ItemsSource="{Binding Model.TablesView}" Grid.Row="1" 
       SelectedItem="{Binding Model.SelectedTable, Mode=TwoWay}" > 
     <ListView.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding Path=.}" 
        Width="{Binding Path=ActualWidth, 
          RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}}" > 
        <TextBlock.InputBindings> 
         <MouseBinding MouseAction="LeftDoubleClick" Command="{Binding DataContext.MoveItemRightCommand, 
             RelativeSource={RelativeSource FindAncestor, 
             AncestorType={x:Type UserControl}}}" 
             CommandParameter="{Binding .}"/> 
        </TextBlock.InputBindings> 
       </TextBlock> 
      </DataTemplate> 
     </ListView.ItemTemplate> 
    </ListView> 
+0

Cảm ơn bạn @Peter –

9

Cách đơn giản nhất để làm điều này là sử dụng System.Windows.InteractivityMicrosoft.Expression.Interactions (cả tự do có sẵn thông qua Blend SDK)

Vì vậy, hãy bắt đầu bằng cách thêm các không gian tên sau vào chế độ xem của bạn

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 

Tiếp theo, nắm bắt sự kiện DoubleClick và pa ss nó vào lệnh:

<ListView ..... > 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="MouseDoubleClick"> 
      <local:EventToCommand Command="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext.myfunction}" /> 
     </i:EventTrigger 
    </i:Interaction.Triggers> 
</ListView> 

Lưu ý: Các EventToCommand được sử dụng là một từ MVVM Light Toolkit và có thể được tải here. Những gì nó thực hiện lệnh (myFunction) ngay khi sự kiện được kích hoạt.

Điều này được dựa trên giả định rằng lệnh myFunction nằm trong DataContext mà người dùng ListView. Nếu không, hãy sửa đổi ràng buộc của EventToCommand thành bất cứ nơi nào lệnh.

+0

Tôi đã thêm một tham chiếu đến Microsoft.Expression.Interactions.dll và bây giờ xây dựng có một lỗi nói dll này không được hỗ trợ trong một dự án WPF. VS 2013. – Rhyous

+0

Cách tìm các tên sự kiện hợp lệ có sẵn như EventName = "MouseDoubleClick" bạn đã sử dụng? Vì nó không cung cấp cho intellisense. –

+0

Điều này sẽ được đánh dấu là câu trả lời. – Jeb

14

Bạn có thể sử dụng Attached Properties để ràng buộc bất kỳ sự kiện nào bạn muốn.

Đối MouseDoubleClick:

namespace Behavior 
{ 
public class MouseDoubleClick 
{ 
    public static DependencyProperty CommandProperty = 
     DependencyProperty.RegisterAttached("Command", 
     typeof(ICommand), 
     typeof(MouseDoubleClick), 
     new UIPropertyMetadata(CommandChanged)); 

    public static DependencyProperty CommandParameterProperty = 
     DependencyProperty.RegisterAttached("CommandParameter", 
              typeof(object), 
              typeof(MouseDoubleClick), 
              new UIPropertyMetadata(null)); 

    public static void SetCommand(DependencyObject target, ICommand value) 
    { 
     target.SetValue(CommandProperty, value); 
    } 

    public static void SetCommandParameter(DependencyObject target, object value) 
    { 
     target.SetValue(CommandParameterProperty, value); 
    } 
    public static object GetCommandParameter(DependencyObject target) 
    { 
     return target.GetValue(CommandParameterProperty); 
    } 
    private static void CommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) 
    { 
     Control control = target as Control; 
     if (control != null) 
     { 
      if ((e.NewValue != null) && (e.OldValue == null)) 
      { 
       control.MouseDoubleClick += OnMouseDoubleClick; 
      } 
      else if ((e.NewValue == null) && (e.OldValue != null)) 
      { 
       control.MouseDoubleClick -= OnMouseDoubleClick; 
      } 
     } 
    } 
    private static void OnMouseDoubleClick(object sender, RoutedEventArgs e) 
    { 
     Control control = sender as Control; 
     ICommand command = (ICommand)control.GetValue(CommandProperty); 
     object commandParameter = control.GetValue(CommandParameterProperty); 
     command.Execute(commandParameter); 
    } 
} 
} 

Và trong XAML:

<ListBox Behavior:MouseDoubleClick.Command="{Binding ....}" 
      Behavior:MouseDoubleClick.CommandParameter="{Binding ....}"/>