Monday, March 17, 2008 11:56 PM codeblock

Silverlight 2.0: A Double Click Manager

One of the missing things of Silverlight is the capability to handle mouse double click events. This problem apply not only to Silverlight 1.0 but also to Silverlight 2.0 Beta 1. Silverlight is rich about Mouse event handling but have two limitations. The first one is the missing right-mouse-button handling due to the presence of a contextual menu for configuration of the plugin. The second thing is the presence of mouse up and down left-button events but not of the click and double-click.

So, I decided to create a small class to handle this problem in a simply way. The class I created behave as a translator that receive mouse-up events and transform them in click/double-click. The only way to discriminate from single to double click is taking care of a brief timeout (300 ms) after the first incoming mouse-up event. If this timeout expires without another incoming mouse-up event we have to raise a click event. Instead, if a second mouse-up arrive we need to raise a double-click event.

Handling events in this way has a little bit problem. We need to receive an event and then wait for another event without blocking the caller and the user interface itself. With javascript I handled this problem using a setTimeout() that reset a flag and raise the correct event after the timeout. With Silverlight 2.0 we need to use a Thread because it is the only way to wait an event without blocking the main thread.

My MouseClickManager class handle the problem in this way. In the next code block I show the main methods of the class:

   1: /// <summary>
   2: /// Handles the click.
   3: /// </summary>
   4: /// <param name="sender">The sender.</param>
   5: /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
   6: public void HandleClick(object sender, MouseButtonEventArgs e)
   7: {
   8:     lock(this)
   9:     {
  10:         if (this.Clicked)
  11:         {
  12:             this.Clicked = false;
  13:             OnDoubleClick(sender, e);
  14:         }
  15:         else
  16:         {
  17:             this.Clicked = true;
  18:             ParameterizedThreadStart threadStart = new ParameterizedThreadStart(ResetThread);
  19:             Thread thread = new Thread(threadStart);
  20:             thread.Start(e);
  21:         }
  22:     }
  23: }
  24:  
  25: /// <summary>
  26: /// Resets the clicked flag after timeout.
  27: /// </summary>
  28: /// <param name="state">The state.</param>
  29: private void ResetThread(object state)
  30: {
  31:     Thread.Sleep(this.Timeout);
  32:  
  33:     lock (this)
  34:     {
  35:         if (this.Clicked)
  36:         {
  37:             this.Clicked = false;
  38:             OnClick(this, (MouseButtonEventArgs)state);
  39:         }
  40:     }
  41: }

In the HandleClick method we receive the incoming events. Probably the event handler of the MouseLeftButtonUp event simply call this method passing sender and arguments. In this method first of all we need to acquire a lock on a shared resource. This resource is the "clicked" flag that indicate if we are handling the first or second event. After acquiring the lock we have two choices. If the clicked flag is set to false we are handling the first click event so we need to set the flag and start a thread that will wait 300 milliseconds before reset the flag. So if the clicked flag has not been reset when we receive the second mouse-up then we are handling a double click event. 

This may appear simply, but it has a little drawback. When we need to raise the single-click event, we are running in a separate thread so we may incur in a cross thread situation and we need to marshal the thread context to the main thread itself to avoid this condition. This is a common problem in windows forms environment and also in WPF. To handle the problem we have to use the Dispatcher object. In this code snippet I show a brief example:

   1: /// <summary>
   2: /// Called when click occure.
   3: /// </summary>
   4: /// <param name="sender">The sender.</param>
   5: /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
   6: private void OnClick(object sender, MouseButtonEventArgs e)
   7: {
   8:     MouseButtonEventHandler handler = Click;
   9:  
  10:     if (handler != null)
  11:         this.Control.Dispatcher.BeginInvoke(handler, sender, e);
  12: }

"Control" is a reference to the control that we have to notify the event. So we will user the Control.Dispatcher.BeginInvoke() method to marshal the event. To use my class MouseClickManager you have simply to crate an instance passing a reference to the control that will receive the click/double click events. Than in the MouseLeftButtonUp event you will call the HandleClick method. The event handler connected to Click and DoubleClick events will be called appropriately.

The class has been designed to configure the the timeout lenght. Some experiments revealed that 200 ms is less, but 400 ms is too much because we will begin to feel the click event delay.

Download: http://blog.boschin.it/download/mouseclickmanager.zip (1 KB) 

Technorati Tag: ,
Filed under:

Comments

# Silverlight中捕获Click及DoubleClick鼠标事件

Sunday, August 17, 2008 10:07 AM by sayo.net

Silverlight中没有鼠标的Click以及DoubleClick事件,至少到目前SilverlightBeta2中还没有。希望在正式版中有相关事件处理(正式版中有太多期待了呵)。

参考了这...

# re: Silverlight 2.0: A Double Click Manager

Wednesday, August 27, 2008 8:06 PM by Scott Edmondson

Thanks Andrea,

That's simple and very effective. I tried another approach which was measuring time between clicks (mouseleftbuttondown events) on the main UI thread, but that was affected by whatever other work was happening on the UI thread between clicks. It was too difficult to tell how long was long enough for a double-click. The separate thread eliminates that problem.

Great idea.

Cheers,

Scott

# Handling a DoubleClick on GridRow in Silverlight &laquo; JTango

Sunday, November 02, 2008 12:03 AM by Handling a DoubleClick on GridRow in Silverlight « JTango

Pingback from  Handling a DoubleClick on GridRow in Silverlight &laquo; JTango

# re: Silverlight 2.0: A Double Click Manager

Saturday, November 08, 2008 11:16 AM by Steve

How do I use this on the page?

ie. I have an image, when I double click on it, I want a popup to show up

# Handling Double Clicks in Silverlight | Blue Onion Software *

Thursday, December 18, 2008 5:13 PM by Handling Double Clicks in Silverlight | Blue Onion Software *

Pingback from  Handling Double Clicks in Silverlight | Blue Onion Software *

# re: Silverlight 2.0: A Double Click Manager

Wednesday, March 11, 2009 12:14 AM by Dr.Syntax

Do you have something that implements mouse click and double click in web pages.

# re: Silverlight 2.0: A Double Click Manager

Tuesday, July 07, 2009 6:24 AM by Andy Cronk

Excellent stuff, I was having trouble with a dispatcher timer as it was giving random results (probably due to the UI thread interfering).

# SL3(silverlight 3) 控件的双击事件

Monday, August 03, 2009 6:50 PM by LJ JIANG

# re: Silverlight 2.0: A Double Click Manager

Wednesday, September 23, 2009 7:04 PM by celtinmlein

<a href="jahshaka.org/.../member.php Mummy</a>

embrigerifoksteron

Leave a Comment

(required) 
(required) 
(optional)
(required)