How can I catch both single-click and double-click

2020-02-09 01:32发布

问题:

I can catch a single-click on a TextBlock like this:

private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
    MessageBox.Show("you single-clicked");
}

I can catch a double-click on a TextBlock like this:

private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
    if (e.LeftButton == MouseButtonState.Pressed)
    {
        if (e.ClickCount == 2)
        {
            MessageBox.Show("you double-clicked");
        }
    }
}

But how do I catch them both on a single TextBlock and differentiate between the two?

回答1:

You need to fire the event after the click sequence is over... when is that? I suggest using a timer. The MouseDown event would reset it and increase the click count. When timer interval elapses it makes the call to evaluate the click count.

    private System.Timers.Timer ClickTimer;
    private int ClickCounter;

    public MyView()
    {
        ClickTimer = new Timer(300);
        ClickTimer.Elapsed += new ElapsedEventHandler(EvaluateClicks);
        InitializeComponent();
    }

    private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
    {
        ClickTimer.Stop();
        ClickCounter++;
        ClickTimer.Start();
    }

    private void EvaluateClicks(object source, ElapsedEventArgs e)
    {
        ClickTimer.Stop();
        // Evaluate ClickCounter here
        ClickCounter = 0;
    }

Cheers!



回答2:

If you need to detect the difference, I suggest you use a control such as Label that does the work for you:

label.MouseDown += delegate(object sender, MouseEventArgs e)
{
    if (e.ClickCount == 1)
    {
        // single click
    }
};

label.MouseDoubleClick += delegate
{
    // double click
};

EDIT: My advice was following from documentation on MSDN:

The Control class defines the PreviewMouseDoubleClick and MouseDoubleClick events, but not corresponding single-click events. To see if the user has clicked the control once, handle the MouseDown event (or one of its counterparts) and check whether the ClickCount property value is 1.

However, doing so will give you a single click notification even if the user single clicks.



回答3:

You must use a timer to differentiate between the two. Add a timer to your form in the GUI (easiest that way - it will automatically handle disposing etc...). In my example, the timer is called clickTimer.

private bool mSingleClick;

private void TextBlock_MouseUp(object sender, MouseButtonEventArgs e)
{

    if (e.Button == MouseButtons.Left)
    {
        if (e.ClickCount < 2)
        {
            mSingleClick = true;
            clickTimer.Interval = System.Windows.Forms.SystemInformation.DoubleClickTime;
            clickTimer.Start();
        }
        else if (e.ClickCount == 2)
        {
            clickTimer.Stop();
            mSingleClick = false;
            MessageBox.Show("you double-clicked");
        }
    }
}

private void clickTimer_Tick(object sender, EventArgs e)
{
    if (mSingleClick)
    {
        clickTimer.Stop();
        mSingleClick = false;
        MessageBox.Show("you single-clicked");
    }
}


回答4:

You are simply can use MouseDown event and count click number, like this:

if (e.ChangedButton == MouseButton.Left && e.ClickCount == 2)
{
    // your code here
}


回答5:

You could do it on MouseUp instead of MouseDown. That way you can ask the ClickCount property for the total number of clicks, and decide what to do from that point.



回答6:

I did it this Way and it works perfectly

If e.Clicks = 2 Then
            doubleClickTimer.Stop()
        ElseIf e.Clicks = 1 Then
            doubleClickTimer.Enabled = True
            doubleClickTimer.Interval = 1000
            doubleClickTimer.Start()


        End If


 Private Sub doubleClickTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles doubleClickTimer.Tick

        OpenWebPage("abc")
        doubleClickTimer.Stop()
    End Sub


回答7:

It's my working solution :)

    #region message label click --------------------------------------------------------------------------
private Timer messageLabelClickTimer = null;

private void messageLabel_MouseUp(object sender, MouseButtonEventArgs e)
{
  Debug.Print(e.ChangedButton.ToString() + " / Left:" + e.LeftButton.ToString() + "  Right:" + e.RightButton.ToString() + "  click: " + e.ClickCount.ToString());
  // in MouseUp (e.ClickCount == 2) don't work!!  Always 1 comes.
  // in MouseDown is set e.ClickCount succesfully  (but I don't know should I fire one clicked event or wait second click)

  if (e.ChangedButton == MouseButton.Left)
  {
    if (messageLabelClickTimer == null)
    {
      messageLabelClickTimer = new Timer();
      messageLabelClickTimer.Interval = 300;
      messageLabelClickTimer.Elapsed += new ElapsedEventHandler(messageLabelClickTimer_Tick);
    }

    if (! messageLabelClickTimer.Enabled)                                                 
    { // Equal: (e.ClickCount == 1)
      messageLabelClickTimer.Start();
    }
    else  
    { // Equal: (e.ClickCount == 2)
      messageLabelClickTimer.Stop();

      var player = new SoundPlayer(ExtraResource.bip_3short);               // Double clicked signal
      player.Play();
    }
  }
}

private void messageLabelClickTimer_Tick(object sender, EventArgs e)
{ // single-clicked
  messageLabelClickTimer.Stop();

  var player = new SoundPlayer(ExtraResource.bip_1short);                  // Single clicked signal
  player.Play();
}    
#endregion


回答8:

My issue was with single/double-clicking rows in a DataGrid in WPF. For some reason the ButtonDown events weren't firing, only the OnMouseLeftButtonUp event was. Anyway, I wanted to handle the single-click differently from the double-click. It looks me a little time (I'm sure the solution isn't perfect, but it appears to work) to distill the problem down until I got it down to the below. I created a Task which calls an Action and that Action's target can be updated by a second click. Hope this helps someone!

private Action _clickAction;
private int _clickCount;

private void Grid_OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    Debug.WriteLine("Button Click Occurred");

    _clickCount++;

    if (_clickCount == 1)
    {
        _clickAction = SingleClick;
    }

    if (_clickCount > 1)
    {
        _clickAction = DoubleClick;
    }

    if (_clickCount == 1)
    {
        Task.Delay(200)
            .ContinueWith(t => _clickAction(), TaskScheduler.FromCurrentSynchronizationContext())
            .ContinueWith(t => { _clickCount = 0; });
    }
}

private void DoubleGridClick()
{
    Debug.WriteLine("Double Click");
}

private void SingleGridClick()
{
    Debug.WriteLine("Single Click");
}