【问题标题】:Cleanest single click + double click handling in Silverlight?Silverlight中最干净的单击+双击处理?
【发布时间】:2009-08-13 20:27:39
【问题描述】:

我一直在寻找处理双击的各种方法,然后作者添加了一些处理单击的 if 代码。现在 Silverlight 3 中是否有一个标准,每个人都在使用它来处理列表框的单击和双击?

【问题讨论】:

  • 我对双击和右键单击需要在 Silverlight 中进行破解感到非常恼火...
  • 我同意。我可以看到右键单击有问题的地方,但我会认为双击是一件容易的事情。

标签: silverlight-3.0 double-click


【解决方案1】:

如果你使用Reactive Extensions (Rx)库,支持双击的代码就简单多了:

Observable.FromEvent<MouseButtonEventArgs>(myControl, "MouseLeftButtonDown").TimeInterval().Subscribe(evt =>
        {
            if (evt.Interval.TotalMilliseconds <= 300)
            {
                // Do something on double click
            }
        });

【讨论】:

  • 其实这是错误的,虽然非常轻微。应该检查 Interval.TotalMilliseconds,因为如果您只检查 Interval.Milliseconds,双击也将是 2 小时 3 分钟 500 毫秒。
  • 很好,我已经修改了。
【解决方案2】:

一次编写使用方便....

 import YourProject.Utils; //must for using extentions

 button1.AddDoubleClickHandler((s, e) =>
            {
                Debug.WriteLine("You can use this DoubleClick extention method
                           for any UIElement in SL !");
            });         

//这是我的工具

namespace YourProject.Utils
{
public class DoubleClick
{

    public DoubleClick()
    {
        this._lastClick = DateTime.Now;
    }

    private  TimeSpan DoubleClickThreshold = TimeSpan.FromMilliseconds(450);
    private  DateTime _lastClick;

    public event MouseButtonEventHandler MouseDoubleClick;

    public void DoubleClicked(object sender, MouseButtonEventArgs e)
    {
        if (DateTime.Now - this._lastClick <= DoubleClickThreshold)
        {
            MouseDoubleClick(sender, e);
        }
        this._lastClick = DateTime.Now;
    }

    internal void AddHandler(UIElement ctl)
    {
        ctl.AddHandler(UIElement.MouseLeftButtonUpEvent, new MouseButtonEventHandler(this.DoubleClicked), true);
    }
}

public static class DoubleClickExtentions
{
    public static void AddDoubleClickHandler(this UIElement ctl, MouseButtonEventHandler MouseDoubleClick)
    {
        DoubleClick doubleClick = new DoubleClick();
        doubleClick.MouseDoubleClick += MouseDoubleClick;

        doubleClick.AddHandler(ctl);
    }
}
}

【讨论】:

    【解决方案3】:

    我喜欢这种方法: http://www.domagoj.pavlesic.com/DoubleClick-in-Silverlight

    优点:你有单击、双击和单击延迟事件(所以你可以确定,不会有双击)。

    【讨论】:

      【解决方案4】:

      我已经根据以下文章的方法实现了一种干净的方式来注册 DoubleClick 事件:

      http://yinyangme.com/blog/post/The-simplest-way-to-detect-DoubleClick-in-Silverlight.aspx http://www.domagoj.pavlesic.com/DoubleClick-in-Silverlight

      要使用它,你只需要通过扩展方法注册/注销处理程序:

      element.AddDoubleClickHandler(Element_DoubleClick);
      element.RemoveDoubleClickHandler(Element_DoubleClick);
      

      代码如下:

          using System;
      using System.Windows;
      using System.Windows.Input;
      
      namespace System.Windows
      {
          public class DoubleClickHelper
          {
              private const long DoubleClickSpeed = 500;
              private const double MaxMoveDistance = 10;
      
              private static long lastClickTicks = 0;
              private static Point lastPosition;
              private static WeakReference lastSender;
      
              internal static bool IsDoubleClick(object sender, MouseButtonEventArgs e)
              {
                  Point position = e.GetPosition(null);
                  long clickTicks = DateTime.Now.Ticks;
                  long elapsedTicks = clickTicks - lastClickTicks;
                  long elapsedTime = elapsedTicks / TimeSpan.TicksPerMillisecond;
                  bool quickClick = (elapsedTime <= DoubleClickSpeed);
                  bool senderMatch = (lastSender != null && sender.Equals(lastSender.Target));
      
                  if (senderMatch && quickClick && DoubleClickHelper.Distance(position, lastPosition) <= MaxMoveDistance)
                  {
                      // Double click!
                      lastClickTicks = 0;
                      lastSender = null;
                      return true;
                  }
      
                  // Not a double click
                  lastClickTicks = clickTicks;
                  lastPosition = position;
                  if (!quickClick)
                      lastSender = new WeakReference(sender);
                  return false;
              }
      
              private static double Distance(Point pointA, Point pointB)
              {
                  double x = pointA.X - pointB.X;
                  double y = pointA.Y - pointB.Y;
                  return Math.Sqrt(x * x + y * y);
              }
      
              public bool HasHandlers { get { return this.MouseDoubleClick != null; } }
      
              private WeakReference target;
      
              public event MouseButtonEventHandler MouseDoubleClick;
              private void OnMouseDoubleClick(MouseButtonEventArgs args)
              {
                  if (this.MouseDoubleClick != null && this.target.IsAlive)
                      this.MouseDoubleClick(this.target.Target, args);
              }
      
              public DoubleClickHelper(FrameworkElement target)
              {
                  this.target = new WeakReference(target);
      
                  target.MouseLeftButtonDown += target_MouseLeftButtonDown;
              }
      
              void target_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
              {
                  if (DoubleClickHelper.IsDoubleClick(sender, e))
                      this.OnMouseDoubleClick(e);
              }
          }
      
          public static class DoubleClickExtension
          {
              public static DoubleClickHelper GetDoubleClickHelper(DependencyObject obj)
              {
                  return (DoubleClickHelper)obj.GetValue(DoubleClickHelperProperty);
              }
              public static void SetDoubleClickHelper(DependencyObject obj, DoubleClickHelper value)
              {
                  obj.SetValue(DoubleClickHelperProperty, value);
              }
              public static readonly DependencyProperty DoubleClickHelperProperty =
                  DependencyProperty.RegisterAttached("DoubleClickHelper", typeof(DoubleClickHelper), typeof(DoubleClickExtension), new PropertyMetadata(null));
      
              public static void AddDoubleClickHandler(this FrameworkElement target, MouseButtonEventHandler handler)
              {
                  DoubleClickHelper helper = target.GetValue(DoubleClickHelperProperty) as DoubleClickHelper;
                  if (helper == null)
                  {
                      helper = new DoubleClickHelper(target);
                      target.SetValue(DoubleClickHelperProperty, helper);
                  }
      
                  helper.MouseDoubleClick += handler;
              }
      
              public static void RemoveDoubleClickHandler(this FrameworkElement target, MouseButtonEventHandler handler)
              {
                  DoubleClickHelper helper = target.GetValue(DoubleClickHelperProperty) as DoubleClickHelper;
                  if (helper == null) return;
      
                  helper.MouseDoubleClick -= handler;
                  if(!helper.HasHandlers)
                      target.SetValue(DoubleClickHelperProperty, null);           
      
              }
          }
       }
      

      【讨论】:

        【解决方案5】:

        Silverlight 5 中有一种更简单的方法,它支持MouseButtonEventArgs.ClickCount。因此,您可以附加一个普通的 MouseLeftButtonDown 处理程序,然后检查:

        private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs args)
        {
            if (args.ClickCount == 1)
                return;
        
            // handle double-click
        }
        

        【讨论】:

          【解决方案6】:

          这是我为控件实现的一个类,以及下面用于树视图的第二个派生类(Silverlight Toolkit)。只需使用要检查双击的控件实例化它并为 DoubleClicked 事件添加处理程序。它使用计时器来尝试模拟双击事件。如果您认为延迟会更好,您可以更改延迟。

          Public Class DoubleClickHelper
          Public Event DoubleClicked(ByVal sender As FrameworkElement)
          Private WithEvents UI As FrameworkElement
          
          Sub New(ByRef UI As FrameworkElement)
              Me.UI = UI
              UI.AddHandler(UIElement.MouseLeftButtonDownEvent, New MouseButtonEventHandler(AddressOf UI_MouseLeftButtonDown), True)
              InitTimer()
          End Sub
          
          Public Delay As Single = 0.2
          Private _dblclick As Boolean = False
          Private _timer As New System.Windows.Threading.DispatcherTimer()
          Protected Property DoubleClick() As Boolean
              Get
                  Return _dblclick
              End Get
              Set(ByVal value As Boolean)
                  _dblclick = value
                  InitTimer()
              End Set
          End Property
          
          Private Sub InitTimer()
              RemoveHandler _timer.Tick, AddressOf timer_Tick
              _timer.Stop()
              _timer = New System.Windows.Threading.DispatcherTimer()
              _timer.Interval = TimeSpan.FromSeconds(Delay)
              AddHandler _timer.Tick, AddressOf timer_Tick
              _timer.Start()
          End Sub
          Protected Overridable Sub timer_Tick(ByVal sender As Object, ByVal e As EventArgs)
              DoubleClick = False
          End Sub
          
          Protected Overridable Sub UI_MouseLeftButtonDown(ByVal sender As Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) Handles UI.MouseLeftButtonDown
              If DoubleClick Then
                  HandleDoubleClick(sender)
              Else
                  HandleFirstClick(sender)
              End If
          End Sub
          
          Protected Overridable Sub HandleDoubleClick(ByVal sender As FrameworkElement)
              RaiseEvent DoubleClicked(sender)
          End Sub
          
          Protected Overridable Sub HandleFirstClick(ByVal sender As FrameworkElement)
              DoubleClick = True
          End Sub
          

          结束类

          Public Class TreeViewItemDoubleClickHelper
          Inherits DoubleClickHelper
          
          Private SameSelection As Boolean = False
          Private WithEvents TreeView As TreeView = Nothing
          
          Public Sub New(ByVal TreeView As TreeView)
              MyBase.New(TreeView)
              Me.TreeView = TreeView
          End Sub
          
          'This event happens after MouseLeftButtonDown
          Private Sub TreeView_SelectedItemChanged(ByVal sender As Object, ByVal e As System.Windows.RoutedPropertyChangedEventArgs(Of Object)) Handles TreeView.SelectedItemChanged
              SameSelection = e.OldValue Is e.NewValue
          End Sub
          
          Protected Overrides Sub UI_MouseLeftButtonDown(ByVal sender As Object, ByVal e As System.Windows.Input.MouseButtonEventArgs)
              'MyBase.UI_MouseLeftButtonDown(sender, e)
              If DoubleClick Or SameSelection Then
                  HandleDoubleClick(sender)
                  SameSelection = False
                  DoubleClick = False
              Else
                  HandleFirstClick(sender)
              End If
          End Sub
          

          结束类

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-08-12
            • 2014-05-17
            • 1970-01-01
            • 1970-01-01
            • 2011-02-19
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多