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>

當然,實現方法不止上述兩種,還可以通過行為等其它方式來實現。

源碼下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM