一、改造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>

二、以下是两种推荐的方法来实现在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结合使用:
<ListView x:Name="myListView">
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <EventSetter Event="MouseDoubleClick" Handler="OnListViewItemDoubleClick"/>
            <!-- 或者使用Interactivity的行为 -->
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseDoubleClick">
                    <i:InvokeCommandAction Command="{Binding DataContext.ItemDoubleClickedCommand, RelativeSource={RelativeSource AncestorType=ListView}}"/>
                    <!-- 使用CommandParameter传递当前项到命令 -->
                    <i:InvokeCommandAction.CommandParameter>
                        <MultiBinding Converter="{StaticResource YourConverter}">
                            <Binding />
                        </MultiBinding>
                    </i:InvokeCommandAction.CommandParameter>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Style>
    </ListView.ItemContainerStyle>
    <ListView.ItemTemplate>
        <!-- DataTemplate定义省略... -->
    </ListView.ItemTemplate>
</ListView>

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

方法2:使用Attached Behavior

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

public static class DoubleClickBehavior
    public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached(
        "Command",
        typeof(ICommand),
        typeof(DoubleClickBehavior),
        new FrameworkPropertyMetadata(null, OnCommandChanged));
    public static void SetCommand(DependencyObject element, ICommand value)
        element.SetValue(CommandProperty, value);
    public static ICommand GetCommand(DependencyObject element)
        return (ICommand)element.GetValue(CommandProperty);
    private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        var listViewItem = d as ListViewItem;
        if (listViewItem != null)
            listViewItem.MouseDoubleClick += ListView_MouseDoubleClick;
    private static void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        var item = (sender as ListViewItem)?.Content;
        var command = GetCommand(sender as DependencyObject);
        if (command != null && command.CanExecute(item))
            command.Execute(item);

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

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

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

向item添加其下的listview 可以对listview进行增删改操作 对listview任意一个item的子集listview的item对象进行增删改操作 <Window x:Class="ListviewInItemAddList.MainWindow" xml...
ListView只有双击事件,同时里面的ListItem大多也是通过数据绑定获得的,很难在页面上直接操作。 虽然没有单机事件,但是ListView有一个SelectionChanged事件,可以变相的当作单机事件。 可是这样依然不够,我们需要知道的我们点击的是哪一行,这个可以通过触发事件后通过ListView.SelectionChanged属性来直接获得所点击的那一行的控件,相当于是直接为每一行添加了一个点击事件
在一次使用WPF ListView的时候,我发现在MVVM模式下在ListView开启虚拟化的情况下,将ListViewItem的IsSelected属性与一个对应的布尔值进行双向绑定。 文档目录结构如下: 源码如下: NotifyBase.cs using System.ComponentModel; using System.Runtime.CompilerServices; namespace WpfApp10 public class NotifyBase : INotifyProp
WPF实现分页后,使用ListView显示图片列表,利用SelectionChanged实现单机事件列表的某个图片,并显示到Image控件,如图所示。 但是当我通过单机事件某一项后,切换下一页或其他页面对ListView列表进行刷新时,程序会再次触发SeletionChanged(因为选项发生了改变)。找了好多方法无法解决,最终,通过自己的调试找到了一个极其简单且好用的方法,即添加一个判断。 if(imageList.SelectedItem == null) retur
wangnaisheng: 还有其他几种方式可以用来在List<EntityTemp>中进行查找: 使用Find方法(如果EntityTemp类实现了IEquatable<T>接口): 如果你定义了EntityTemp类并实现了IEquatable<EntityTemp>接口,你可以使用List<T>.Find方法。你需要重写Equals和GetHashCode方法来比较两个EntityTemp实例是否相等。 使用Where方法结合ToList或SingleOrDefault: 你可以使用Where方法过滤列表中的元素,然后使用ToList获取所有匹配的结果,或者使用SingleOrDefault获取单个结果(如果没有找到匹配项则返回默认值,如果有多个匹配项则抛出异常)。 使用循环遍历: 传统的方式是使用for或foreach循环遍历整个列表,并检查每个元素是否满足条件。 使用BinarySearch(需要先排序): 如果列表已经按照某个属性排序,你可以使用BinarySearch方法来进行快速查找。但在此之前,你需要确保列表是已排序的,并且实现IComparable<T>或提供一个比较器。 使用字典(如果经常需要基于键进行查找): 如果你频繁地需要根据Name或其他属性来查找实体,可以考虑将实体放入Dictionary<string, EntityTemp>中,其中string是Name,而EntityTemp是对应的实体。这样可以实现O(1)时间复杂度的查找。 每种方法都有其适用场景,选择哪种取决于你的具体需求,比如性能要求、代码可读性、数据结构的特性等。如果你的数据集不大,而且查询不频繁,那么简单的FirstOrDefault或者Find就足够了。对于大数据集或频繁查询的情况,可能需要考虑更高效的数据结构如字典。 【C# 】使用List<实体类> GJ10086SR: 这个查找还有别的方法吗? 医学图像DICOM医学影像文件格式详解 wangnaisheng: 参考一下:https://lxblog.com/qianwen/share?shareId=dd404c94-55dc-447a-8783-f7270db30fb7 出现什么问题,问问大模型或是百度。。。 医学图像DICOM医学影像文件格式详解 fine lucky: 表情包就是这样读,但是读不进去,是因为图像格式没有尾缀嘛?它的类型是文件,不是.dcm。搞不懂