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:
- don’t use SingleClick and DoubleClick on the same element
- 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
- 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);
The basic idea behind this approach is based on Mike Snow’s blog post – thanks!