一、改造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提供的类似功能。
步骤如下:
- 在XAML中引用交互行为库:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
- 为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:
【C# 】使用List<实体类>
GJ10086SR:
医学图像DICOM医学影像文件格式详解
wangnaisheng:
医学图像DICOM医学影像文件格式详解
fine lucky: