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>
當然,實現方法不止上述兩種,還可以通過行為等其它方式來實現。