最近项目中需要封装Silverlight控件,需求提出控件要有双击事件,例如TreeView叶子节点或ListBox的item项双击后进行相应操作。但是Silverlight本身并没有双击事件,不知道4.0或5.0时会不会支持双击,希望微软的大侠们考虑考虑。
下面说一下双击事件的模拟过程:
1、设计思想
首先自己考虑了一下,双击其实就是短时间内单击了两次某FrameworkElement。给两次单击事件打上时间戳,然后判断时间相减小于给定的时间那就算双击了。后来又参考了网上一些朋友写的模拟实现,原理也都差不多。于是乎想想还是自己写一个吧,换了种思路,用定时器实现之。定义一个定时器,第一次点击某FrameworkElement时启动它,在第一次Tick事件中先停止定时器,然后判断是不是这个FrameworkElement已经被点击了两次,如果符合此条件则响应该FrameworkElement的双击事件。
2、主要代码
服务代码:
Code
public class DoubleClickHelper
{
private DispatcherTimer timer;
private FrameworkElement currentFrameworkElement;
public event EventHandler<DoubleClickEventArgs> OnDoubleClick;
public DoubleClickHelper()
{
if (timer == null)
{
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(300);
timer.Tick += new EventHandler(timer_Tick);
}
}
public void SendMessage(FrameworkElement fe)
{
if (fe == null)
{
return;
}
if (timer.IsEnabled == false)
{
timer.Start();
}
if (!fe.Equals(currentFrameworkElement))
{
fe.Tag = 1;
}
else
{
fe.Tag = 2;
}
currentFrameworkElement = fe;
}
void timer_Tick(object sender, EventArgs e)
{
if (timer.IsEnabled == true)
{
timer.Stop();
}
if ((int)currentFrameworkElement.Tag == 2)
{
OnDoubleClick(null, new DoubleClickEventArgs(currentFrameworkElement));
}
currentFrameworkElement = null;
}
}
public class DoubleClickEventArgs : EventArgs
{
private FrameworkElement currentFrameworkElement;
public FrameworkElement CurrentFrameworkElement
{
get { return currentFrameworkElement; }
set { currentFrameworkElement = value; }
}
public DoubleClickEventArgs( FrameworkElement fe )
{
currentFrameworkElement = fe;
}
}
调用代码:
Code
public partial class MainPage : UserControl
{
private DoubleClickHelper treeDoubleClickHelper = new DoubleClickHelper();
private DoubleClickHelper listDoubleClickHelper = new DoubleClickHelper();
public MainPage()
{
InitializeComponent();
treeDoubleClickHelper.OnDoubleClick += new EventHandler<DoubleClickEventArgs>(treeDoubleClickHelper_OnDoubleClick);
listDoubleClickHelper.OnDoubleClick += new EventHandler<DoubleClickEventArgs>(listDoubleClickHelper_OnDoubleClick);
}
void listDoubleClickHelper_OnDoubleClick(object sender, DoubleClickEventArgs e)
{
txtListDoubleClickResult.Text +=
(e.CurrentFrameworkElement as System.Windows.Controls.ListBoxItem).Content.ToString() + "\n";
}
void treeDoubleClickHelper_OnDoubleClick(object sender, DoubleClickEventArgs e)
{
TreeViewItem item = e.CurrentFrameworkElement as TreeViewItem;
if (!item.HasItems)
{
txtTreeDoubleClickResult.Text += item.Header.ToString() + "\n";
}
}
private void TreeViewItem_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
FrameworkElement fe = e.OriginalSource as FrameworkElement;
treeDoubleClickHelper.SendMessage(fe.ParentOfType<TreeViewItem>());
}
private void ListBox_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
FrameworkElement fe = e.OriginalSource as FrameworkElement;
listDoubleClickHelper.SendMessage(fe.ParentOfType<ListBoxItem>());
}
}
3、总结
目前看基本的应用可以,但是需要一些其它的支持,比如FrameworkElement的扩展方法,用以得到想要的FrameworkElement类型。还有不是实时响应双击事件,由于是定时器实现,如果双击速度特别快,就会发现双击之后会有停顿才响应事件。其它的可能还有别的BUG,待以后慢慢发现吧。
完整代码:
DoubleClickTest.rar