Question

I would like to control if the user do single click or double click when is clicked with the mouse. So I use this code:

private void MouseSingleClickCommand(RoutedEventArgs e)
{
    _dtMouseClick.Start();
}


private void MouseClick_Tick(object sender, System.EventArgs e)
{
    _dtMouseClick.Stop();

    //my one click code
}



private void MouseDoubleClickCommand(MouseButtonEventArgs e)
{
    _dtMouseClick.Stop();
    //code of the double click
}

_dt is a DispatcherTimer that is created in the constructor of the view model:

_dtMouseClick =
                new System.Windows.Threading.DispatcherTimer(
                new TimeSpan(0, 0, 0, 0, 200),
                System.Windows.Threading.DispatcherPriority.Background,
                MouseClick_Tick,
                System.Windows.Threading.Dispatcher.CurrentDispatcher);

However the code of one click is always executed because the dispatcher is not stopped.

Why?.

Thanks.

EDIT: I include the axml of the button:

<StackPanel Height="Auto" HorizontalAlignment="Left" Margin="548,0,0,0" Name="stpBotnoesBasicos" VerticalAlignment="Top" Width="Auto">
                    <Button Content="Buscar" Height="23" Name="btn01" Width="75">
                        <i:Interaction.Triggers>
                            <i:EventTrigger EventName="Click">
                                <cmd:EventToCommand Command="{Binding MouseSingleClickCommand}" PassEventArgsToCommand="True"/>
                            </i:EventTrigger>

                                <i:EventTrigger EventName="MouseDoubleClick">
                                <cmd:EventToCommand Command="{Binding MouseDoubleClickCommand}" PassEventArgsToCommand="True"/>
                                </i:EventTrigger>
                            </i:Interaction.Triggers>
                    </Button>
</Stackpannel>
Was it helpful?

Solution 2

This solution is based on the solution from this other question:

base solution

If I use the PreviewMouseLeftButtonDown to control when is single click or double click works, instead of using two events (click and doubleclick).

So I solve the problem with this code:

This first method control the click with the mouse.

private void MouseLeftButtonDownCommand(MouseButtonEventArgs e)
        {

            if (e.ClickCount == 1)
            {
                _dtMouseClick.Start();
            }

            else if(e.ClickCount > 1)
            {
                _dtMouseClick.Stop();

                //the code of the double click
            }
        }

This method is the method that is linked to the DispatcherTimer, that is execute if is not stopped with the second click of the mouse.

private void MouseClick_Tick(object sender, System.EventArgs e)
        {
            _dtrMouseClick.Stop();

            //code of the single click                
        }

The dispatcherTimer is create in the constructor of the view model

_dtBotonBuscarMouseClick =
                new System.Windows.Threading.DispatcherTimer(
                new TimeSpan(0, 0, 0, 0, 250),
                System.Windows.Threading.DispatcherPriority.Background,
                MouseClick_Tick,
                System.Windows.Threading.Dispatcher.CurrentDispatcher);
            _dtMouseClick.Stop();

The interval is 250ms that is the interval that is the time that the user has to double click.

In this solution, I use the same way to stop the dispatcherTimer, the stop() method, but for some reason if I use the two events (click and mouseDoubleClick) the dispatcherTimer is not stopped in the double click and if I use the MouseLeftButtonDown event the solution works.

EDIT

This solution for me works as I expect.

In the MouseLeftButtonDown event, I check if the ClickCount is 1 or 2. If the count is 1, then I start the timer. So the timer will execute its code if is not stopped before.

The timer will be stopped if the second click is a double click. This is when the ClickCounter > 1. If the lapse time between clicks is enough big, then clickcounter is always 1, so this event, MouseLeftButtonDown, control when is double click or not.

When the timer is executed, first I stop it because I want exectued its code once, the code that I want when is only one click.

If I double click, then I stop the timer before the interval is reached, so never is executed, and execute the code that I want when is double click.

OTHER TIPS

You are stopping it after the first tick (_dtMouseClick.Stop(); under MouseClick_Tick). Try the following changes to get a clearer picture:

private void MouseClick_Tick(object sender, System.EventArgs e)
{
    MessageBox.Show("One tick more");
}

And change the Interval to 1 second (new TimeSpan(0, 0, 0, 0, 1000)).

Now, the MessageBox pops up once every second, until you double-click (MouseDoubleClickCommand is called). Inside MouseClick_Tick you have to put the code to be triggered regularly, not a code avoiding the Timer to run.

CLARIFICATION

The expected way in which a timer has to be used consists in three parts: START, DO ANYTHING (on the _tick event), STOP once it is not useful anymore. How to register the number of clicks for example?

Int clicksCounter = 0; //Declared globally.

You store the information you want (number of clicks); and start the timer when required.

private void MouseLeftButtonDownCommand(MouseButtonEventArgs e)
{
     clicksCounter = clicksCounter + 1;
     if (clicksCounter == 1)
     {
         _dtMouseClick.Start(); //(set a small enough interval: 50ms or 10ms or even 1ms).
     }
}

Now you have to check the values of the target variable from the _Tick method (which can stop itself when required), that is:

private void MouseClick_Tick(object sender, System.EventArgs e)
{
   //This event should be called as quickly as possible in order to check clicks at any time
    if(clicksCounter >= 2)
    {
        //Condition met. Reset the variables
        clicksCounter = 0;
        _dtMouseClick.Stop(); 
       MessageBox.Show("The user has clicked the mouse button more than once");
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top