Wednesday, February 9, 2011

Silverlight double click event

We had to perform some business logic when a user double click’s on a Image, unfortunately till the current version of silverilght( version 4.x) there is no double click event. In future versions of silverlight we might get the double click functionality but for right now we will have to get this done by our self. So how do we implement double click event? The trick is to start a timer and check if the MouseLeftButtonDown event is fired again in certain duration(milliseconds).

Code is very simple and short, In the xaml we have a Image with a MouseLeftButtonDown event in the code behind we add a dispatch timer which is a part of  System.Windows.Threading. On the first click start the timer, when next click event is fired check if the timer is active, if the timer is active then it is a double click so go ahead and perform the intended action.

  1.    private DispatcherTimer timer;
  2.    public MainPage()
  3.    {
  4.        InitializeComponent();
  5.        timer = new DispatcherTimer();
  6.        timer.Interval = new TimeSpan(0, 0, 0, 200);
  7.        timer.Tick += new EventHandler(( sender,  e) => { timer.Stop(); });
  8.    }
  9.  
  10.    private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  11.    {
  12.        if (!timer.IsEnabled)
  13.        {
  14.            timer.Start();return;
  15.        }
  16.        timer.Stop();
  17.        HandleDoubleClick();
  18.    }

 

DoubleClick Class
The above functionality can be encapsulated in a class for a cleaner looking code. The class ‘DoubleClick’ has a dispatch timer and a public event. In the constructor you pass the UIElement as parameter and hook the MouseLeftButtonDown event. The timer tick event has an inline event handler defined that will stop the timer on the first tick.

  1. namespace DoubleClickInSL4
  2. {
  3.     using System.Windows.Threading;
  4.     public class DoubleClick
  5.     {
  6.         private const int dblclickDelay = 200;
  7.         private DispatcherTimer timer;
  8.         public event MouseButtonEventHandler MouseDoubleClick;
  9.  
  10.         public DoubleClick(UIElement uiElement)
  11.         {
  12.             timer = new DispatcherTimer();
  13.             timer.Interval = new TimeSpan(0, 0, 0, dblclickDelay);
  14.             timer.Tick += new EventHandler((sender, e) => { timer.Stop(); });
  15.  
  16.             uiElement.MouseLeftButtonDown += new MouseButtonEventHandler(UIElement_MouseLeftButtonDown);
  17.         }
  18.  
  19.         private void UIElement_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  20.         {
  21.             if (!timer.IsEnabled)
  22.             {
  23.                 timer.Start();
  24.                 return;
  25.             }
  26.             timer.Stop();
  27.  
  28.             //HandleDoubleClick();
  29.             if (MouseDoubleClick != null)
  30.             {
  31.                 MouseDoubleClick(sender, e);
  32.             }
  33.         }
  34.     }
  35. }

 

Rx Framework
A very interesting use of the Rx framework can simplify the above code to just couple of lines. In the MouseLeftButtonDown event we add a Observable.FromEvent  and set TimeInterval, so when the event is fired for the first time the timer starts. On the second event the code in the body of lambda will be executed which checks if  duration is greater then 300.

  1. private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  2. {           
  3.    Observable.FromEvent<MouseButtonEventArgs>(this.LayoutRoot, "MouseLeftButtonDown").TimeInterval().Subscribe(evt =>
  4.     {
  5.         if (evt.Interval.Milliseconds >= 300)
  6.         {
  7.             // Do something on double click
  8.         }
  9.     });
  10. }

 

Doubleclick Behaviour
The above code is helpful for application that handles the logic directly in the codebehind, so how about MVVM application where the application logic is handled in the model view. A decent solution for such a scenario would be to write a behavior that implements the double click functionality. There are many posts which explain how to create a behaviors so I will not go in details, basically this double click behavior have a dependency property named as DoubleClickCommand that will bind to a property in the view model of type ICommand. I created a class called as DelegateCommand which implements the interface ICommand, this class will be instantiated in the view model and assigned to view models property. 

  1. namespace DoubleClickInSL4
  2. {
  3.     using System.Windows.Threading;
  4.     public class DoubleClickBehavior : Behavior<UIElement>
  5.     {
  6.         private const int dblclickDelay = 200;
  7.         private DispatcherTimer timer;
  8.  
  9.         public object CommandParameter
  10.         {
  11.             get { return (object)GetValue(CommandParameterProperty); }
  12.             set { SetValue(CommandParameterProperty, value); }
  13.         }
  14.         public ICommand DoubleClickCommand
  15.         {
  16.             get { return (ICommand)GetValue(DoubleClickCommandProperty); }
  17.             set { SetValue(DoubleClickCommandProperty, value); }
  18.         }
  19.  
  20.         public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register
  21.             ("CommandParameter", typeof(object), typeof(DoubleClickBehavior), new PropertyMetadata(CommandParameterChanged));
  22.         private static void CommandParameterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { }
  23.  
  24.         public static readonly DependencyProperty DoubleClickCommandProperty = DependencyProperty.Register
  25.             ("DoubleClickCommand", typeof(ICommand), typeof(DoubleClickBehavior), new PropertyMetadata(DoubleClickCommandChanged));
  26.         private static void DoubleClickCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { }
  27.  
  28.         public DoubleClickBehavior()
  29.         {
  30.             timer = new DispatcherTimer();
  31.             timer.Interval = new TimeSpan(0,0, 0, 0, dblclickDelay);
  32.             timer.Tick += new EventHandler((sender, e) =>
  33.             { timer.Stop(); });
  34.         }
  35.         protected override void OnAttached()
  36.         {
  37.             base.OnAttached();
  38.             AssociatedObject.MouseLeftButtonDown += UIElement_MouseLeftButtonDown;
  39.         }
  40.         protected override void OnDetaching()
  41.         {
  42.             base.OnDetaching();
  43.             AssociatedObject.MouseLeftButtonDown -= UIElement_MouseLeftButtonDown;
  44.         }
  45.  
  46.         private void UIElement_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  47.         {
  48.             if (!timer.IsEnabled)
  49.             {
  50.                 timer.Start();
  51.                 return;
  52.             }
  53.             timer.Stop();
  54.  
  55.             //HandleDoubleClick();
  56.             if (CommandParameter != null)
  57.                 DoubleClickCommand.Execute(CommandParameter);
  58.         }
  59.     }
  60. }
  61.  
  62. namespace DoubleClickInSL4
  63. {
  64.      public class DelegateCommand : ICommand   
  65.      {   
  66.          Func<object, bool> canExecute;   
  67.          Action<object> executeAction;   
  68.          bool canExecuteCache;   
  69.          public DelegateCommand(Action<object> executeAction, Func<object, bool> canExecute)  
  70.          {  
  71.              this.executeAction = executeAction;
  72.              this.canExecute = canExecute;
  73.          }  
  74.          #region ICommand Members  
  75.          public bool CanExecute(object parameter)  
  76.          {  
  77.              bool temp = canExecute(parameter);
  78.              if (canExecuteCache != temp)
  79.              {  
  80.                  canExecuteCache = temp;
  81.                  if (CanExecuteChanged != null)
  82.                  {  
  83.                      CanExecuteChanged(this, new EventArgs());
  84.                  }  
  85.              }  
  86.              return canExecuteCache;
  87.          }  
  88.          public event EventHandler CanExecuteChanged;  
  89.          public void Execute(object parameter)  
  90.          {  
  91.              executeAction(parameter);
  92.          }  
  93.            #endregion
  94.      }
  95. }

Here is the code for the MainPage.xaml.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. using System.Windows.Documents;
  6. using System.Windows.Input;
  7. using System.Windows.Threading;
  8. using System.Windows.Interactivity;
  9.  
  10. namespace DoubleClickInSL4
  11. {    
  12.     public class myViewModel
  13.     {
  14.         public ICommand DoubleCommand { get; set; }
  15.         public myViewModel()
  16.         {
  17.             DoubleCommand = new DelegateCommand(myAction, canExe);
  18.         }     
  19.         private void myAction(object param)
  20.         { //Write your action here }
  21.         private bool canExe(object param)
  22.         { return true; }
  23.     }
  24.  
  25.     public partial class MainPage : UserControl
  26.     {      
  27.         public MainPage()
  28.         {
  29.             InitializeComponent();
  30.             Image.DataContext = new myViewModel();
  31.         }
  32.     }
  33. }
 

Here is the xaml for the MainPage.xaml.

  1. <UserControl x:Class="DoubleClickInSL4.MainPage"
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5.     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6.     xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
  7.     xmlns:Local="clr-namespace:DoubleClickInSL4"
  8.     mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400">
  9.     <UserControl.Resources>
  10.         <Local:myViewModel x:Name="vm"/>
  11.     </UserControl.Resources>
  12.     <Grid x:Name="LayoutRoot" Background="White" Height="300" Width="400">
  13.         <Image x:Name="Image" Source="Images/80_20.jpg" >
  14.             <i:Interaction.Behaviors>
  15.                                 <Local:DoubleClickBehavior DoubleClickCommand="{Binding DoubleCommand}" CommandParameter="{Binding ElementName=Image,Path=Source}"/>
  16.             </i:Interaction.Behaviors>
  17.                                </Image>
  18.     </Grid>
  19. </UserControl>

 




Extending Silverlight mouse events


SharpGIS has a very interesting blog post about extending the silverlight mouse events. Including double-clicks they have provided many more extensions with source code and a online demo.
http://www.sharpgis.net/post/2009/05/02/Extending-Silverlighte28099s-mouse-events.aspx

Wednesday, February 2, 2011

Exam 70-506 ( TS: Silverlight 4, Development )

 
In November I gave the beta exam for silverlight 4, it took me more then four hours to complete the exam questions, review and comment. For beta exams you do not get the score right away, exactly after three months I got an email from Microsoft stating that I passed the beta exam for silverlight  and now I am certified Silverlight 4,Developer.

Silverlight exam is now released and is available through prometric testing centers and the exam number is 70-506. I like  beta exams because they are challenging, one reason is you don't get ready made material to study all you have is MSDN documents, blogs,some samples and forums. There is a huge community support for silverlight and luckily there where some good books in the market. I find many of my fellow programmers worried about not able to find definite material to prepare for the exam. I am going to put together a list of  useful links that will help to prepare for the exam.

Exam details on Microsoft learning.
http://www.microsoft.com/learning/en/us/Exam.aspx?ID=70-506&Locale=en-us#tab2

Some good books
Professional Silverlight 4
Silverlight 4 in Action
Pro Silverlight for the Enterprise
Microsoft Silverlight 4 Data and Services Cookbook

Forums
http://forums.silverlight.net
http://social.msdn.microsoft.com/Forums/eu/silverlightdeveloper/threads

Links

Silverlight Show Getting ready for silverlight exam 70-506
http://www.silverlightshow.net/items/Getting-ready-for-the-exams-Part-1.aspx
http://www.silverlightshow.net/items/Getting-ready-for-Microsoft-Silverlight-Exam-70-506-Part-2.aspx
http://www.silverlightshow.net/items/Getting-ready-for-Microsoft-Silverlight-Exam-70-506-Part-3.aspx
http://www.silverlightshow.net/items/Getting-ready-for-Microsoft-Silverlight-Exam-70-506-Part-4.aspx
http://www.silverlightshow.net/items/Getting-ready-for-Microsoft-Silverlight-Exam-70-506-Part-5.aspx
http://www.silverlightshow.net/items/Getting-ready-for-Microsoft-Silverlight-Exam-70-506-Part-6.aspx
http://www.silverlightshow.net/items/Getting-ready-for-Microsoft-Silverlight-Exam-70-506-Part-7.aspx

Mark’s Blog
http://mark.mymonster.nl/2010/10/25/exam-preparationsilverlight-4-development70-506part-1/
http://mark.mymonster.nl/2010/10/26/exam-preparationsilverlight-4-development70-506part-2/
http://mark.mymonster.nl/2010/10/31/exam-preparationsilverlight-4-development70-506part-3/
http://mark.mymonster.nl/2010/11/01/exam-preparationsilverlight-4-development70-506part-4/
http://mark.mymonster.nl/2010/11/02/exam-preparationsilverlight-4-development70-506part-5/
http://mark.mymonster.nl/2010/11/03/exam-preparationsilverlight-4-development70-506part-6/
http://mark.mymonster.nl/2010/11/04/exam-preparationsilverlight-4-development70-506part-7/

Microsoft training catalog
http://learning.microsoft.com/Manager/Catalog.aspx?qry=silverlight&nav=0&btn=1

Silverlight Documents on MSDN
http://msdn.microsoft.com/en-us/library/cc838158(VS.95).aspx

Silverlight 4 Hands On Labs
http://www.silverlight.net/learn/handsonlabs/

List of all popular books
http://www.silverlight.net/learn/books/

Chanel 9 - What's New in Silverlight 4
http://channel9.msdn.com/Learn/Courses/Silverlight4/Overview

Videos and screen cast
http://www.silverlight.net/learn/videos/all/
http://blogs.msdn.com/b/joestagner/archive/2008/08/01/44-silverlight-videos.aspx
http://sandrinodimattia.net/blog/post/Complete-Expression-Blend-and-Silverlight-5-day-OnRamp-training-course-All-videos-all-assets-download-packages-in-one-place.aspx

 

For developers having right experience the exams are not really tough but I would say the questions are tricky so make sure you have good hands-on experience with silverlight before you appear for the exam. Although the exam focuses on sivlerlight 4, I would say Visual Studio 2010 and Expression Blend are inevitable tools for a silverlight developer. I have tried to put together some of the good links, if you find some more good links please put them in the comments