zoukankan      html  css  js  c++  java
  • WPF: 在 MVVM 设计中实现对 ListViewItem 双击事件的响应

    ListView 控件最常用的事件是 SelectionChanged;如果采用 MVVM 模式来设计 WPF 应用,通常,我们可以使用行为(如 InvokeCommandAction)并结合命令来实现对该事件的响应;如果我们要实现对 ListViewItem 双击事件的响应——也就是说,双击 ListView 中的某一项——又该怎么做呢?

    首先, ListView 并没有提供相关的事件;其次,ListViewItem 虽然有 PreviewMouseDoubleClick(隧道事件),然而在 UI 中,我们却没有适合的方法来调用。那么究竟有没有办法来解决这个问题呢?答案肯定是有,以下便是两种解决方案。第一种是相对简单,在 DataTemplate 中使用 MouseBinding;第二种方法是通过附加属性,相比第一种略为复杂一些。来看代码:

    方法一:

    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}">
                <TextBlock.InputBindings>
                    <MouseBinding Command="{Binding DataContext.ShowInfoCommand, ElementName=window}" MouseAction="LeftDoubleClick" />
                </TextBlock.InputBindings>
            </TextBlock>
        </DataTemplate>
    </ListView.ItemTemplate>

    可以看到,在上述代码中,我们添加了 MouseBinding,指定属性 MouseAction 为 LeftDoubleClick,并将其 Command 属性与 ViewModel 中的命令绑定;这样,就可以实现对左键双击当前元素(TextBlock)的响应,也正好可以理解为双击当前的 ListViewItem。不过有一点需要注意的是, ListViewItem 的 HorizontalContentAlignment 属性值默认是 Left,所以在上述 DataTemplate 中 TextBlock 并不会充满 ListViewItem,所以还需要添加以下样式:

    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        </Style>
    </ListView.ItemContainerStyle>

     方法二:

    新建一个类,并在其中定义一个附加属性,代码如下:

        public class ControlDoubleClick : DependencyObject
        {
            public static readonly DependencyProperty CommandProperty =
                DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(ControlDoubleClick), new PropertyMetadata(OnCommandChanged));
    
            public static ICommand GetCommand(Control target)
            {
                return (ICommand)target.GetValue(CommandProperty);
            }
    
            public static void SetCommand(Control target, ICommand value)
            {
                target.SetValue(CommandProperty, value);
            }
    
            private static void Element_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
            {
                Control control = sender as Control;
                ICommand command = GetCommand(control);
    
                if (command.CanExecute(null))
                {
                    command.Execute(null);
                    e.Handled = true;
                }
            }
    
            private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                Control control = d as Control;
                control.PreviewMouseDoubleClick += new MouseButtonEventHandler(Element_PreviewMouseDoubleClick);
            }
        }

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

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

    当然,实现方法不止上述两种,还可以通过行为等其它方式来实现。

    源码下载

    作者:WPInfo

    本文系作者原创,欢迎转载;如需转载,请注明出处。

    公众号:.NET之窗 (WinDotNET),更多原创、优质技术文章,欢迎扫码关注。

  • 相关阅读:
    听过闰年闰月,可你听过闰秒吗?
    在线学习的“后浪”:现代学习系统中的人工智能
    idea在service窗口中显示现有微服务启动类
    Intellij IDEA导入项目出现Cannot load settings from file错误
    HttpServletRequest的getRequestURL方法获取不到https协议请求问题
    新增gitignore无效的解决办法
    访问腾讯存储桶中的文件,跨域问题的解决
    线程池的创建方法推荐
    TreeMap在自定义排序时的坑
    vue.js功能学习
  • 原文地址:https://www.cnblogs.com/wpinfo/p/6565992.html
Copyright © 2011-2022 走看看