2009-08-13 17 views
6

Znalazłem różne metody radzenia sobie z podwójnym kliknięciem, a następnie autor uderzył w niektóre, jeśli kod do obsługi pojedynczych kliknięć. Czy istnieje teraz standard w Silverlight 3, z którego korzystają wszyscy, aby obsłużyć zarówno pojedyncze, jak i podwójne kliknięcie na listach?Najczystsze jedno kliknięcie + obsługa dwukrotnego kliknięcia w Silverlight?

+5

Jestem bardzo zirytowany faktem, że podwójne kliknięcie prawym przyciskiem myszy i musi być hack w Silverlight ... – Stilgar

+0

zgadzam. Widzę, że kliknięcie prawym przyciskiem jest problematyczne, ale wydaje mi się, że podwójne kliknięcie było łatwe. – Josh

Odpowiedz

-1

Oto klasa, którą zaimplementowałem dla kontroli, a także druga klasa pochodna poniżej dla widoku drzewa (Toolkit Silverlight). Wystarczy utworzyć instancję za pomocą kontrolki, którą chcesz sprawdzić, by uzyskać podwójne kliknięcia i dodać moduł obsługi zdarzenia DoubleClicked. Używa timera, aby spróbować zasymulować podwójne kliknięcie. Możesz zmienić opóźnienie, jeśli uważasz, że będzie działać lepiej.

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 

End Class

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 

End Class

10

Jeśli używasz biblioteki Reactive Extensions (Rx) kod wspierać podwójne kliknięcie jest znacznie prostsza:

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

W rzeczywistości jest to błędne, choć bardzo nieznaczne. Należy sprawdzić Interval.TotalMilliseconds, ponieważ jeśli zaznaczysz tylko Interval.Milliseconds, kliknięcie dwukrotne będzie również na 2 godziny, 3 minuty i 500 ms. –

+0

Dobry połów, polepszyłem to. –

+0

Dobrze. Warto awansować teraz ;-) –

0

I zostały wdrożone czystą drogę do rejestrowania zdarzeń DoubleClick na podstawie podejść do następujących artykułów:

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

aby go użyć, wystarczy zarejestrować/wyrejestrować obsługi za pomocą metod rozszerzeń:

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

Oto kod:

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);   

     } 
    } 
} 
2

Write Once użyciu łatwo ....

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 !"); 
      });   

// Tu jest mój util

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); 
    } 
} 
} 
+0

Dzięki człowieku, to naprawdę działa dla mnie .. utrzymaj to .. –

0

Jest łatwiejszy sposób w Silverlight 5, który obsługuje MouseButtonEventArgs.ClickCount. Tak, można po prostu dołączyć normalny MouseLeftButtonDown obsługi i sprawdzić:

private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs args) 
{ 
    if (args.ClickCount == 1) 
     return; 

    // handle double-click 
} 
Powiązane problemy