Mouse Double Click for WPF in MVVM using a clean Behavior with Command Binding

I wanted to capture the double click event, which is actually the MouseLeftButtonDown with the e.ClickCount ==2.

Since I transitioned to a new WPF project, handed off the Silverlight work, I have been trying to keep the same MVVM pattern. I wanted to get the double click off of my TreeViewItem so the child node could invoke the ViewModel to execute a Command.

Here is the behavior I wrote to handle this simple task.

Snippet

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Controls;

namespace Seekford.Behaviors
{
    public static class MouseDoubleClickBehavior
    {
        /// <summary>
        /// Hooks up a weak event against the source Selectors MouseDoubleClick
        /// if the Selector has asked for the HandleDoubleClick to be handled
        ///�
        /// If the source Selector has expressed an interest in not having its
        /// MouseDoubleClick handled the internal reference
        /// </summary>
        private static void OnHandleDoubleClickCommandChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement ele = d as FrameworkElement;
            if (ele != null)
            {
                ele.MouseLeftButtonDown -= OnMouseDoubleClick;
                if (e.NewValue != null)
                {
                    ele.MouseLeftButtonDown += OnMouseDoubleClick;
                }
            }
        }

        /// <summary>
        /// TheCommandToRun : The actual ICommand to run
        /// </summary>
        public static readonly DependencyProperty DoubleClickCommandProperty =
            DependencyProperty.RegisterAttached("DoubleClickCommand",
                typeof(ICommand),
                typeof(MouseDoubleClickBehavior),
                new FrameworkPropertyMetadata((ICommand)null,
                    new PropertyChangedCallback(OnHandleDoubleClickCommandChanged)));

        /// <summary>
        /// Gets the TheCommandToRun property. �
        /// </summary>
        public static ICommand GetDoubleClickCommand(DependencyObject d)
        {
            return (ICommand)d.GetValue(DoubleClickCommandProperty);
        }

        /// <summary>
        /// Sets the TheCommandToRun property. �
        /// </summary>
        public static void SetDoubleClickCommand(DependencyObject d, ICommand value)
        {
            d.SetValue(DoubleClickCommandProperty, value);
        }

        #region Handle the event

        /// <summary>
        /// Invoke the command we tagged.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            //check for double clicks.
            if (e.ClickCount != 2)
                return;
            FrameworkElement ele = sender as FrameworkElement;

            DependencyObject originalSender = e.OriginalSource as DependencyObject;
            if (ele == null || originalSender == null)
                return;

            ICommand command = (ICommand)(sender as DependencyObject).GetValue(DoubleClickCommandProperty);

            if (command != null)
            {
                if (command.CanExecute(null))
                    command.Execute(null);
            }
        }
        #endregion
    }

}

Hopefully this helps you.

Oh, how to use. Almost forgot:

Snippet

xmlns:infraBehaviors="clr-namespace:Seekford.Behaviors;assembly=Seekford"

Snippet

 <Grid infraBehaviors:MouseDoubleClickBehavior.DoubleClickCommand="{Binding MyCommand}"  HorizontalAlignment="Stretch" >
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>       �
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition></RowDefinition>
                </Grid.RowDefinitions>
                <TextBlock Text="{Binding Name}" TextWrapping="Wrap" FontWeight="Bold"  Grid.Column="0"  />
            </Grid>

Of course, make your own namespace and correct accordingly. But you already knew that.

Happy Coding!

0 Replies to “Mouse Double Click for WPF in MVVM using a clean Behavior with Command Binding”

  1. I implemeted this to a Grid. Whenever I click the mouse OnMouseDoubleClick fires on the first mouse click so that e.ClickCount != 2 always fails as e.ClickCount is 1.

    //check for double clicks.
    if (e.ClickCount != 2)
    return;

    How do I make OnMouseDoubleClick fire only when I select one of the rows in the grid during mouse double click.

    1. This event will fire every mouseclick. When you double click, it should fire with a clickcount ==2. Put a TRACE statement in that method with the clickcount to watch its behavior. breakpoints obviously don’t work, since they break control.

  2. This was exactly what I was looking for to implement single and double clicking on listbox items using WPF and MVVM. Thanks so much for the post Brian!

  3. Excellent!! i have problem with DoubleClickCommand where it is in User Control. i have one page which contain User Control and inside this i have used infraBehaviors:MouseDoubleClickBehavior.DoubleClickCommand=”{Binding MyCommand}” now when i click on button nothing happend if i putted in Page without user control then it is working fine.

    Please help me if you have some time! seeking for your co-operation and looking forward.

    Thanks,
    Imdadhusen

  4. Michael Ennis :
    You sir, are a gentleman and a scholar! Did a quick VB conversion and it is working like a charm. I think I’m going to augment a lot more controls with this type of event binding!

    I have to agree! Extremely useful! Thanks for publishing, Brian!

  5. Brian,

    Your code looks great and it was easy to create a demo app using the code except for one minor problem.
    I am having trouble making my version of your code invoke my command. When testing, I found that the Dependency Property DoubleClickCommandProperty was invoked but no other properties or methods were called in the class MouseDoubleClickBehavior.

    The class MouseDoubleClickBehavior was copied and moved into a separate project Pdm.Behaviors. I changed the xmlns appropriately, as witnessed by the successful usage of the DoubleClickCommandProperty . I changed MyCommand to EditVendor and implemented that command in the MainWindowViewModel.cs. The MainWindowViewModel is the DataContext for the MainWindow.

    However, my clicks and double clicks are not being recognized, nothing happens. If you have a moment I could sure use your help.

    Thanks.

    Andy Nelms

  6. Brian,

    Never mind. I found it. I changed MyCommand to EditVendor in the xaml when I should have changed it to EditVendorCommand. Thanks for the code. It works great.

  7. Great, this works fine in Grid.. how can i make it to use in DataGrid for RowClick Action and also in third party controls like XamDataGrid(Infragistics).

    Thanks in advance

Leave a Reply

Your email address will not be published. Required fields are marked *