May 24 2010

DoubleClick in Silverlight

Category: EN | SilverlightDomagoj @ 15:56

doubleclickdemo As you probably know, Silverlight does not support double click event, not even a single click event on most elements (I think there is an event called Click only on Buttons). Single click can be emulated via MouseLeftButtonDown and MouseLeftButtonUp, but it is wrong to bind it to only one out of these two. “Real” Click event combines MouseLeftButtonDown and MouseLeftButtonUp and both of them must be raised over the same element to form the click. If you still want to use only one event and you are aware that it is not the best solution, than you should use MouseLeftButtonUp.

Before going into double click scenario, let me point out that double click is not “natural” on the Web and you should not use it there if you want your application to be user friendly. This is just a proof of concept, an example that it can be done, but it is generally not a good idea to implement a double click in a web application.

Double click is a bit more complicated than single click. In this case, you should catch four events in total – two MouseLeftButtonDowns and two MouseLeftButtonUps, and they all should be fired above the same element, in a short period of time (less than 400 milliseconds) and the mouse cursor should not change its position. It is not as complicated as it sounds and I have prepared a small class (source and demo are at the bottom of the post) you can use freely in your projects (I’m using it in one and it works like a charm).

But, there is one more problem you should be aware of – after the first click (the first pair of MouseLeftButtonDown and MouseLeftButtonUp) we don’t know will the user stop clicking, or will he click once more to produce a double click. Since we expect him to do it under 400 milliseconds, the decision whether this is a single or double click can be made 400 ms after the first MouseLeftButtonUp. This amount of time can seem small enough to ignore it, but in real life scenario this will be noted by user and he will feel that single click is not responsive enough. For example, if you put SingleClick and DoubleClick events on an element, and the user clicks on it once, he will wait 400 ms for an application to respond to a SingleClick event.

There are several things you can do to solve this issue:

  1. don’t use SingleClick and DoubleClick on the same element
  2. use SingleClick and DoubleClick for complemental actions – for example, like in Windows Explorer, single click will select a file, and double click will open it
  3. show to the user that you have “captured” his single click, but don’t execute it’s command just yet, wait to be sure that double click timeout is over

In my DoubleClick class there are three events you can attach to:

  • SingleClick – fires when the user clicks on an element (does one MouseLeftButtonDown and one MouseLeftButtonUp); fires every time, even if user double clicks!
  • SingleClickDelayed – fires when user clicks on an element (does one MouseLeftButtonDown and one MouseLeftButtonUp) and doesn’t do the other pair of Down&Up, so you can be sure that this is no double click
  • DoubleClick – fires when user double clicks (two MouseLeftButtonDowns and two MouseLeftButtonUps) on the same position, clicks must be produces under 400 ms

What events should you use?

  • if you need only single click, use SingleClick
  • if you need only double click, use DoubleClick
  • if you need both, but actions are complemental (see scenario no. 2), use SingleClick and DoubleClick
  • if you need both, but actions are not complemental, use SingleClickDelayed and DoubleClick – please be aware that there will be a noticable delay between user click and the moment when SingleClickDelayed fires; you can use SingleClick event to let the user know that the click was detected (show a progress bar, change the color or something) and SingleClickDelayed to do the action

How to use this class? It is pretty straightforward:

  • add using Dizzy.DoubleClick;
  • extend the element and hook up events:
    DoubleClickExtender dce = new DoubleClickExtender(rect1);
    dce.SingleClick += new MyEventHandler(dce_SingleClick);
    dce.SingleClickDelayed += new MyEventHandler(dce_SingleClickDelayed);
    dce.DoubleClick += new MyEventHandler(dce_DoubleClick);

doubleclickcode

Here you can find a demo project (full source, includes the class doubleclick.cs) and here you can see it in action. Happy programming!

The basic idea behind this approach is based on Mike Snow’s blog post – thanks!

Tags:

Comments

1.
Grawa Grawa United States says:

Why did you decided to use 400ms? You have some resource for why 400ms is expected / suggested time span for double-click?

BTW you talk about user-friendly stuff and yet you are using reCAPTCHA thingy Smile

2.
Domagoj Domagoj Croatia says:

Hi, thanks for commenting.

I've read on MSDN (msdn.microsoft.com/.../bb760404(VS.85).aspx) that Windows default double click timeout was 500 ms, but I find it a bit too long, so I've cut it down to 400 ms, especially because there is that delay...

Regarding reCaptcha, sorry - that's the only way to get rid of tons of spam every day. Smile

3.
Grawa Grawa United States says:

You can try Aksimet spam service - it works great!

4.
Domagoj Domagoj Croatia says:

I've enabled Aksimet, few days ago and I get a few spam comments every day. Not fun... :-(

5.
eagle eagle says:

good!

6.
Martin Kirk Martin Kirk says:

Using a delay, and then wait until the delay itself ends is wrong !

I implemented doubleclick when making my javascript editor : www.mdk-photo.com/editor

this is how i did it:

var timeout = 400; // ms
var enabled = false;

element.onclick -> {
    if(enabled){ doubleClickEvent() }
    enabled = true;
    setTimeout( { enabled = false } , timeout );
    
    singleClickEvent()
}

my algorithm is way more advanced in the editor, but the principal is the same...

7.
Martin Kirk Martin Kirk says:

Also...

click and doubleclick events shouldn't react on mouseposition differences

instead do this:

object objSender = null;
onMouseDown = { objSender = sender; }
onMouseUp = { if(objSender == sender){ SingleClick() } }

8.
Domagoj Domagoj says:

@Martin - thanks for commenting.
Regarding the delay - you're right, but there are scenarios where that can be useful, that's way my example has two events - with and without delay. Event SingleClick does exactly what you're suggesting, the other one waits for the delay.
You're right about mouse position, I'll change that. Thanks!

Add comment


(Will show your Gravatar icon)

biuquote
  • Comment
  • Preview
Loading