0

My Requirement: I want to set custom command for my WPF button, inside the custom command execution I want to know whether the command executed by mouse single click or double click. Also when the customCommand's CanExecute returns false, I want the button to go on disable state. please refer below for more details.

Description: Hi, In WPF I have set custom command for my button. When I click the button(For both single click and double click) the command gets executed. Inside the custom command I want to handle a separate action for single click and double click. Is it possible to find whetehr button single clicked or double this inside commands?? I use .Net 4.0, c#4.0

Note : I referred this How to bind a command in WPF to a double click event handler of a control? but I faced a limitation here.
Limitation: When I set the custom command for my button then on CustomCommand CanExcute returns false the button goes to disable state. but As per the above Suggestion, by setting the command to mouse binding and setting the mouse binding to button works but when CanExecute returns false, the button doesnt goes to disable state. How to overcome this

public CustomCommand: ICommandd { public bool CanExecute(object parameter) { //arbitrary logic }

public void Execute(object parameter)
{
    if(MouseSingleClick)
    {
        perform ActionA;
    }
    if(MouseDoubleClick)
    {
        PerformActionB;
    }
}

}

Thanks in Advance.

Community
  • 1
  • 1
Sivasubramanian
  • 935
  • 7
  • 22
  • Does it depend which button of the Mouse is clicked or you want to fire the event only on left button single click or double click? – Sandesh Apr 10 '14 at 04:23
  • Hi @aks81, Thanks for your interest. I want to initiate the custom command on both single click and double click(mouse left button) but inside the custom command i want to find whether it is single click or double click, so if it is single click I perform one action , if it is double click i perform another action. please let me know if you need more information. – Sivasubramanian Apr 10 '14 at 04:36

2 Answers2

1

I was able to use this and tweak it to use it in MVVM friendly way.

I am giving a working example using Cinch framework.

I hoe this helps you give the idea to get going.

MyViewModel

public class MyViewModel : INotifyPropertyChanged
{

    private static DispatcherTimer myClickWaitTimer =
            new DispatcherTimer (
                    new TimeSpan (0, 0, 0, 0, 150),
                    DispatcherPriority.Background,
                    mouseWaitTimer_Tick,
                    Dispatcher.CurrentDispatcher);

    private static void mouseWaitTimer_Tick (object sender, EventArgs e)
    {
        myClickWaitTimer.Stop ();

        Debug.WriteLine ("Single Click Executed");//PerformActionA
    }

    public ICommand CinchSingleClickCommand { get; private set; }
    public ICommand CinchDoubleClickCommand { get; private set; }


    public MyViewModel ()
    {
        CinchSingleClickCommand = new SimpleCommand<object, EventToCommandArgs> (CanExecuteSingleCinch, ExecuteSingleCinch);
        CinchDoubleClickCommand = new SimpleCommand<object, EventToCommandArgs> (CanExecuteDoubleCinch, ExecuteDoubleCinch);
        myClickWaitTimer.Stop ();
    }

    private void ExecuteDoubleCinch (EventToCommandArgs obj)
    {
        if (obj.EventArgs is MouseEventArgs)
        {
            myClickWaitTimer.Stop ();
            Debug.WriteLine ("Double Click Executed");//PerformActionB
            var mouseEvent = obj.EventArgs as MouseEventArgs;
            mouseEvent.Handled = true;
        }
    }

    private bool CanExecuteDoubleCinch (object arg)
    {
        return true;
    }

    private void ExecuteSingleCinch (EventToCommandArgs obj)
    {
        if (!(obj.EventArgs is MouseEventArgs))
        {
            myClickWaitTimer.Start ();
            var mouseEvent = obj.EventArgs as RoutedEventArgs;
            mouseEvent.Handled = true;
        }
    }

    private bool CanExecuteSingleCinch (object arg)
    {
        return true;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisePropertyChanged (string propertyName)
    {
        var pc = PropertyChanged;
        if (pc != null)
            pc (this, new PropertyChangedEventArgs (propertyName));
    }
}

You can play with the TimeSpan constructor to set how much delay do you want to keep between the single click and the double click.

The View

<Window x:Class="DataGridTesting.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
            xmlns:cinch="clr-namespace:Cinch;assembly=Cinch.WPF"
            Title="MainWindow"
            Height="350"
            Width="525">
<DockPanel>
    <Button x:Name="button"
                    Content="Test">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="MouseDoubleClick">
                <cinch:EventToCommandTrigger Command="{Binding CinchDoubleClickCommand}" />
            </i:EventTrigger>
            <i:EventTrigger EventName="Click">
                <cinch:EventToCommandTrigger Command="{Binding CinchSingleClickCommand}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Button>
</DockPanel>
</Window>

The Code behind for the view

public partial class MainWindow : Window
{
    public MainWindow ()
    {
        InitializeComponent ();
        this.DataContext = new MyViewModel ();
    }
}

I used Nuget Package Manager to pull the required dll's for Cinch, System.Windows.Interactivity and Microsoft.Expression.Interactions

Community
  • 1
  • 1
Sandesh
  • 2,966
  • 1
  • 20
  • 34
  • You can combind the two commands into one and use the `if` statements to differentiate between the single click and the double click. Just for the verification purpose I split the events into two commands – Sandesh Apr 10 '14 at 06:59
  • @asks81 Thank you for spending your time for me. I am trying to implement your code in my project. I havent used cinch framework. Can this be done without cinch assemblies?? – Sivasubramanian Apr 10 '14 at 14:00
  • Yes you can. Just pull the required code from Cinch source code. If you need help just let me know. I will try to create the complete relevant code. Right now I am not in office. I can give the complete code tomorrow. – Sandesh Apr 10 '14 at 14:14
  • fine, I will wait for your sample, meanwhile I will try on my side. – Sivasubramanian Apr 10 '14 at 14:32
  • I was able to create a working example. The code is quite big as I had to copy multiple files to the solution. So I will give the necessary folders you need in your project. Download the source code from Cinch [here](http://cinch.codeplex.com/SourceControl/latest) and extract the zip. Open the path `V2 (VS2010 WPF and SL)\CinchV2` and copy the folders `Commands`, `Events` and `Interactivity` into your solution. Fix the namespace and also please keep the license text file in the cinch folder. You should be able to then execute the above code I gave in the example. – Sandesh Apr 10 '14 at 16:01
  • You are welcome :). So you got your solution running? I would then delete the source code uploaded by me. – Sandesh Apr 14 '14 at 11:03
  • yes I have the local copy of the TestApplication, you can proceed to delete. :) – Sivasubramanian Apr 14 '14 at 11:25
0

The confusion is Button control's default click event shadows over other events like double click, mouse down etc. So May be using a Label is a good idea. You can camouflage it as a button and then use MouseDown and MouseDoubleClick events of the label to do your two different tasks. Use a timer to differentiate single click. Following link shows more detail

double click/ single click

Community
  • 1
  • 1
voddy
  • 950
  • 1
  • 11
  • 21
  • Hi @voddy, using label as a button is not feasible for my scenario. IN my project I am using labels and paths inside my button template. – Sivasubramanian Apr 10 '14 at 14:04