Ho trovato vari metodi per gestire il doppio clic e quindi gli autori eseguono uno schiaffo su alcuni se il codice per la gestione di singoli clic. C'è uno standard ora in Silverlight 3 che tutti usano per gestire sia un singolo che un doppio clic sulle liste?Pulisci singolo clic + doppio clic su Silverlight?
risposta
Ecco una classe che ho implementato per i controlli e anche una seconda classe derivata di seguito per un treeview (Silverlight Toolkit). Basta istanziarlo con il controllo che si desidera controllare per i doppi clic e aggiungere un gestore per l'evento DoubleClicked. Utilizza un timer per provare a simulare un evento di doppio clic. Puoi cambiare il ritardo se pensi che funzionerà meglio.
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
Se si utilizza la libreria Reactive Extensions (Rx) il codice per supportare doppio click è molto più semplice:
Observable.FromEvent<MouseButtonEventArgs>(myControl, "MouseLeftButtonDown").TimeInterval().Subscribe(evt =>
{
if (evt.Interval.TotalMilliseconds <= 300)
{
// Do something on double click
}
});
In realtà, questo è sbagliato, anche se molto leggermente. Si dovrebbe verificare per Interval.TotalMilliseconds, perché se si controlla solo Interval.Milliseconds, un doppio clic sarebbe anche a 2 ore, 3 minuti e 500 ms. –
Buona cattura, ho ammesso questo. –
Buono. Ne vale la pena ora ;-) –
mi piace questo approccio: http://www.domagoj.pavlesic.com/DoubleClick-in-Silverlight
Pro: si dispone di un singolo clic, doppio clic e singoli clic su eventi ritardati (quindi si può essere sicuri, non ci sarà doppio clic).
+1 per semplicità :) –
Ho implementato un modo pulito per registrarsi per gli eventi DoubleClick sulla base degli approcci dei seguenti articoli:
http://yinyangme.com/blog/post/The-simplest-way-to-detect-DoubleClick-in-Silverlight.aspx http://www.domagoj.pavlesic.com/DoubleClick-in-Silverlight
per utilizzarlo, è sufficiente registrare/annullare la registrazione del gestore attraverso metodi di estensione:
element.AddDoubleClickHandler(Element_DoubleClick);
element.RemoveDoubleClickHandler(Element_DoubleClick);
Ecco il codice:
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);
}
}
}
write once usa facilmente ....
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 !");
});
// Ecco il mio 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);
}
}
}
Grazie amico è davvero un lavoro per me..avverti su .. –
C'è un modo più semplice in Silverlight 5, che supporta MouseButtonEventArgs.ClickCount
. Così, si può semplicemente collegare un normale MouseLeftButtonDown
gestore, e controllare:
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs args)
{
if (args.ClickCount == 1)
return;
// handle double-click
}
Sono molto infastidito dal fatto che doppio clic e fare clic destro deve essere un hack in Silverlight ... – Stilgar
Sono d'accordo. Riesco a vedere dove un clic destro è problematico, ma avrei pensato che il doppio clic fosse una cosa facile. – Josh