当前位置:   article > 正文

WPF 在 MVVM 设计中实现ListView双击事件_listview双击编辑

listview双击编辑

一、改造ListView 控件最常用的事件是 SelectionChanged

如果采用 MVVM 模式来设计 WPF 应用,通常,我们可以使用行为(如 InvokeCommandAction)并结合命令来实现对该事件的响应;

如果我们要实现对 ListViewItem 双击事件的响应——也就是说,双击 ListView 中的某一项时应该怎么做呢?


首先, ListView 并没有提供相关的事件;

其次,ListViewItem 虽然有 PreviewMouseDoubleClick(隧道事件),然而在 UI 中,我们却没有适合的方法来调用。

那么究竟有没有办法来解决这个问题呢?

答案肯定是有,以下便是两种解决方案。

方法一

在 DataTemplate 中使用 MouseBinding;

  1. <ListView.ItemTemplate>
  2. <DataTemplate>
  3. <TextBlock Text="{Binding Name}">
  4. <TextBlock.InputBindings>
  5. <MouseBinding Command="{Binding DataContext.ShowInfoCommand, ElementName=window}" MouseAction="LeftDoubleClick" />
  6. </TextBlock.InputBindings>
  7. </TextBlock>
  8. </DataTemplate>
  9. </ListView.ItemTemplate>

可以看到,在上述代码中,我们添加了 MouseBinding,指定属性 MouseAction 为 LeftDoubleClick,并将其 Command 属性与 ViewModel 中的命令绑定;

这样,就可以实现对左键双击当前元素(TextBlock)的响应,也正好可以理解为双击当前的 ListViewItem。不过有一点需要注意的是, ListViewItem 的 HorizontalContentAlignment 属性值默认是 Left,所以在上述 DataTemplate 中 TextBlock 并不会充满 ListViewItem,所以还需要添加以下样式:

  1. <ListView.ItemContainerStyle>
  2. <Style TargetType="ListViewItem">
  3. <Setter Property="HorizontalContentAlignment" Value="Stretch" />
  4. </Style>
  5. </ListView.ItemContainerStyle>

方法二

通过附加属性,相比第一种略为复杂一些。新建一个类,并在其中定义一个附加属性,代码如下:

  1. public class ControlDoubleClick : DependencyObject
  2. {
  3. public static readonly DependencyProperty CommandProperty =
  4. DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(ControlDoubleClick), new PropertyMetadata(OnCommandChanged));
  5. public static ICommand GetCommand(Control target)
  6. {
  7. return (ICommand)target.GetValue(CommandProperty);
  8. }
  9. public static void SetCommand(Control target, ICommand value)
  10. {
  11. target.SetValue(CommandProperty, value);
  12. }
  13. private static void Element_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
  14. {
  15. Control control = sender as Control;
  16. ICommand command = GetCommand(control);
  17. if (command.CanExecute(null))
  18. {
  19. command.Execute(null);
  20. e.Handled = true;
  21. }
  22. }
  23. private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  24. {
  25. Control control = d as Control;
  26. control.PreviewMouseDoubleClick += new MouseButtonEventHandler(Element_PreviewMouseDoubleClick);
  27. }
  28. }

通过代码可以看出,这种方法是名副其实地对 ListViewItem 的 PreviewMouseDoubleClick 事件的响应;接下来,在 XAML 中为 ListViewItem 设置如下样式:

  1. <Window xmlns:behavior="clr-namespace:ListViewItemDoubleClickTest.Behavior"
  2. ...>
  3. <ListView.ItemContainerStyle>
  4. <Style TargetType="ListViewItem">
  5. <Setter Property="HorizontalContentAlignment" Value="Stretch" />
  6. <Setter Property="behavior:ControlDoubleClick.Command" Value="{Binding DataContext.ShowInfoCommand, ElementName=window}" />
  7. </Style>
  8. </ListView.ItemContainerStyle>

二、以下是两种推荐的方法来实现在ViewModel中响应ListViewItem的双击事件

WPF的MVVM(Model-View-ViewModel)设计模式下,处理ListViewItem双击事件时,通常避免直接在视图(View)中写入事件处理代码以保持清晰的职责分离。

方法1:使用System.Windows.Interactivity库和InvokeCommandAction

首先,确保你已经安装了Microsoft Expression Blend SDK(包含System.Windows.Interactivity.dll),或者使用第三方如MVVM Light Toolkit或Prism Library提供的类似功能。

步骤如下:

  1. 在XAML中引用交互行为库:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
  1. 为ListView中的DataTemplate添加一个MouseBinding或EventTrigger与InvokeCommandAction结合使用:
  1. <ListView x:Name="myListView">
  2. <ListView.ItemContainerStyle>
  3. <Style TargetType="{x:Type ListViewItem}">
  4. <EventSetter Event="MouseDoubleClick" Handler="OnListViewItemDoubleClick"/>
  5. <!-- 或者使用Interactivity的行为 -->
  6. <i:Interaction.Triggers>
  7. <i:EventTrigger EventName="MouseDoubleClick">
  8. <i:InvokeCommandAction Command="{Binding DataContext.ItemDoubleClickedCommand, RelativeSource={RelativeSource AncestorType=ListView}}"/>
  9. <!-- 使用CommandParameter传递当前项到命令 -->
  10. <i:InvokeCommandAction.CommandParameter>
  11. <MultiBinding Converter="{StaticResource YourConverter}">
  12. <Binding />
  13. </MultiBinding>
  14. </i:InvokeCommandAction.CommandParameter>
  15. </i:EventTrigger>
  16. </i:Interaction.Triggers>
  17. </Style>
  18. </ListView.ItemContainerStyle>
  19. <ListView.ItemTemplate>
  20. <!-- DataTemplate定义省略... -->
  21. </ListView.ItemTemplate>
  22. </ListView>

这里,我们通过InvokeCommandAction将ListViewItem的双击事件绑定到ViewModel中的命令ItemDoubleClickedCommand上,并且可以通过CommandParameter传递当前选中项的数据上下文。

方法2:使用Attached Behavior

创建一个自定义的附加行为类,该类会监听ListViewItem的双击事件,并在其内部触发一个命令。

  1. public static class DoubleClickBehavior
  2. {
  3. public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached(
  4. "Command",
  5. typeof(ICommand),
  6. typeof(DoubleClickBehavior),
  7. new FrameworkPropertyMetadata(null, OnCommandChanged));
  8. public static void SetCommand(DependencyObject element, ICommand value)
  9. {
  10. element.SetValue(CommandProperty, value);
  11. }
  12. public static ICommand GetCommand(DependencyObject element)
  13. {
  14. return (ICommand)element.GetValue(CommandProperty);
  15. }
  16. private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  17. {
  18. var listViewItem = d as ListViewItem;
  19. if (listViewItem != null)
  20. {
  21. listViewItem.MouseDoubleClick += ListView_MouseDoubleClick;
  22. }
  23. }
  24. private static void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
  25. {
  26. var item = (sender as ListViewItem)?.Content;
  27. var command = GetCommand(sender as DependencyObject);
  28. if (command != null && command.CanExecute(item))
  29. {
  30. command.Execute(item);
  31. }
  32. }
  33. }

然后在XAML中应用这个附加行为:

  1. <ListView x:Name="myListView">
  2. <ListView.ItemContainerStyle>
  3. <Style TargetType="{x:Type ListViewItem}">
  4. <Setter Property="local:DoubleClickBehavior.Command"
  5. Value="{Binding DataContext.ItemDoubleClickedCommand, RelativeSource={RelativeSource AncestorType=ListView}}"/>
  6. </Style>
  7. </ListView.ItemContainerStyle>
  8. <!-- ...其余部分... -->
  9. </ListView>

这两种方法都可以有效地在不违反MVVM原则的情况下,将ListViewItem的双击事件通知给ViewModel进行处理。

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
  

闽ICP备14008679号