Silverlight开发中的疑难杂症-如何为Silverlight添加双击事件

在日常的开发中鼠标的事件是我们使用的最多的事件,但是在Silverlight中,只支持以下六种有限的鼠标事件:MouseEnterMouseLeaveMouseLeftButtonDownMouseLeftButtonUpMouseMoveMouseWheel。这给我们的开发造成了不小的麻烦,还好Silverlight支持强大的附加属性机制,这里就指导大家如何通过附加属性来给Silverlight添加鼠标的双击事件。

附加属性是Silverlight也是WPF中最具创新也是最强大的特性之一,它能够让你在不拥有控件的源码的情况下对其功能进行扩展。关于附加属性的强大我就不在这里叙述了,有感兴趣的朋友可以去查看WPF控件开发揭秘一书,里面有一张专门争对附加属性进行了介绍,网络上和园子里也早就有许多关于附加属性的文章。

这里直接进入主题,首先,我们需要对外提供两种双击事件的处理机制,一种是常用的事件机制,使用自带的MouseButtonEventHandler;另一种是现在比较流行的Command机制,使用ICommand接口。两个附加属性的定义如下:

附加属性的定义
#region  MouseDoubleClick

public   static  MouseButtonEventHandler GetMouseDoubleClick(DependencyObject obj)
{
    
return  (MouseButtonEventHandler)obj.GetValue(MouseDoubleClickProperty);
}

public   static   void  SetMouseDoubleClick(DependencyObject obj, MouseButtonEventHandler value)
{
    obj.SetValue(MouseDoubleClickProperty, value);
}

public   static   readonly  DependencyProperty MouseDoubleClickProperty  =  DependencyProperty.RegisterAttached(
    
" MouseDoubleClick " ,
    
typeof (MouseButtonEventHandler),
    
typeof (MouseEventHelper),
    
new  PropertyMetadata( new  PropertyChangedCallback(OnMouseDoubleClickChanged))); 

#endregion

#region  MouseDoubleClickCommand

public   static  ICommand GetMouseDoubleClickCommand(DependencyObject obj)
{
    
return  (ICommand)obj.GetValue(MouseDoubleClickCommandProperty);
}

public   static   void  SetMouseDoubleClickCommand(DependencyObject obj, ICommand value)
{
    obj.SetValue(MouseDoubleClickCommandProperty, value);
}

public   static   readonly  DependencyProperty MouseDoubleClickCommandProperty  =
    DependencyProperty.RegisterAttached(
" MouseDoubleClickCommand " typeof (ICommand),  typeof (MouseEventHelper),  new  PropertyMetadata(OnMouseDoubleClickChanged)); 

#endregion

附加属性在定义上与依赖属性的主要区别就是附加属性是通过DependencyProperty.RegisterAttached的方式进行注册的,而依赖属性是通过DependencyProperty.Register方法进行注册的。这里还提供了GetSet方法,这两个方法是提供给在Xaml代码中进行附加属性注册时使用的。大家在进行附加属性的定义时,可以通过输入propa再按一下Tab键进行代码生成。大家可以注意到,在两个属性的定义中我们都传入了一个PropertyChangedCallback,这就是所谓的扩展点,在这个回调中,我们可以根据自己的逻辑进行相应的处理,这里我们只是注册了UIElementMouseLeftButtonDown事件,这样可以让我们的附加属性能够作用于所有继承自UIElement的控件(基本上就是全部的控件了吧~)。

双击事件的实现思路非常简单,就是通过在MouseLeftButtonDown中记录鼠标点击的时间,然后用上次的点击时间跟这次的点击时间进行比较,如果两次点击间隔小于200ms则作为一次双击处理,触发对应的事件和命令,完整的代码如下:

 

MouseEventHelper
///   <summary>
///  Silverlight鼠标事件帮助类
///   </summary>
public   class  MouseEventHelper
{
    
#region  Dependency Properties

    
#region  模拟鼠标双击事件

    
#region  MouseDoubleClick

    
public   static  MouseButtonEventHandler GetMouseDoubleClick(DependencyObject obj)
    {
        
return  (MouseButtonEventHandler)obj.GetValue(MouseDoubleClickProperty);
    }

    
public   static   void  SetMouseDoubleClick(DependencyObject obj, MouseButtonEventHandler value)
    {
        obj.SetValue(MouseDoubleClickProperty, value);
    }

    
public   static   readonly  DependencyProperty MouseDoubleClickProperty  =  DependencyProperty.RegisterAttached(
        
" MouseDoubleClick " ,
        
typeof (MouseButtonEventHandler),
        
typeof (MouseEventHelper),
        
new  PropertyMetadata( new  PropertyChangedCallback(OnMouseDoubleClickChanged))); 

    
#endregion

    
#region  MouseDoubleClickCommand

    
public   static  ICommand GetMouseDoubleClickCommand(DependencyObject obj)
    {
        
return  (ICommand)obj.GetValue(MouseDoubleClickCommandProperty);
    }

    
public   static   void  SetMouseDoubleClickCommand(DependencyObject obj, ICommand value)
    {
        obj.SetValue(MouseDoubleClickCommandProperty, value);
    }

    
public   static   readonly  DependencyProperty MouseDoubleClickCommandProperty  =
        DependencyProperty.RegisterAttached(
" MouseDoubleClickCommand " typeof (ICommand),  typeof (MouseEventHelper),  new  PropertyMetadata(OnMouseDoubleClickChanged)); 

    
#endregion

    
private   static  DateTime ?  _lastClickTime  =   null ;
    
private   const   int  MaxClickInterval  =   200 ; // ms

    
private   static   void  OnMouseDoubleClickChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        UIElement element 
=  obj  as  UIElement;
        
if  (element  !=   null )
        {
            element.MouseLeftButtonDown 
+=   new  MouseButtonEventHandler(element_MouseLeftButtonDown);
        }
    }

    
///   <summary>
    
///  通过检测两次鼠标单机的间隔来模拟鼠标双击事件
    
///   </summary>
    
///   <param name="sender"></param>
    
///   <param name="e"></param>
     static   void  element_MouseLeftButtonDown( object  sender, MouseButtonEventArgs e)
    {
        
// 进入双击事件
         if  (_lastClickTime.HasValue  &&  DateTime.Now.Subtract(_lastClickTime.Value).TotalMilliseconds  <=  MaxClickInterval)
        {
            
// 触发事件
            MouseButtonEventHandler handler  =  (sender  as  UIElement).GetValue(MouseDoubleClickProperty)  as  MouseButtonEventHandler;
            
if  (handler  !=   null )
            {
                handler(sender, e);
            }
            ICommand command 
=  (sender  as  UIElement).GetValue(MouseDoubleClickCommandProperty)  as  ICommand;
            
if  (command  !=   null )
            {
                
if  (command.CanExecute(sender))
                {
                    command.Execute(sender);
                }
            }
            
// 重新计时
            _lastClickTime  =   null ;
        }
        
else
        {
            _lastClickTime 
=  DateTime.Now;
        }
    } 

    
#endregion

    
#endregion
}

是不是觉得很简单?按照上面的流程大家就可以尽情的扩展Silverlight,帮她加上各种各样的功能了!~

你可能感兴趣的:(silverlight)