¿cuál es la mejor manera de detectar cuándo se ha mantenido presionado un botón del mouse en un elemento en particular durante un período de tiempo específico?WPF - Detecta el mouse durante un período de tiempo establecido
Respuesta
Necesita agregar MouseDown
y MouseUp
controladores al objeto. En el registro MouseDown
DateTime.Now
. Si en el controlador MouseUp
:
DateTime.Now.Subtract(clickTime).TotalSeconds > your_seconds_value
luego disparar un nuevo evento MouseClickedForXseconds
.
Si no desea esperar un evento de mouse arriba, entonces necesita iniciar un temporizador en el método MouseDown
que desencadena el evento MouseClickedForXSeconds
. Este temporizador se cancelará con un evento de mouse arriba.
Gracias por la punta, he hecho una propiedad adjunta para evitar cualquier código subyacente:
using System;
using System.Windows;
using System.Windows.Threading;
/// <summary>
/// Represents a particular mouse button being pressed
/// </summary>
public enum MouseButtonType
{
/// <summary>
/// Default selection
/// </summary>
None,
/// <summary>
/// Left mouse button
/// </summary>
Left,
/// <summary>
/// Right mouse button
/// </summary>
Right,
/// <summary>
/// Either mouse button
/// </summary>
Both
}
/// <summary>
/// Provides functionality for detecting when a mouse button has been held
/// </summary>
public class MouseDownWait
{
/// <summary>
/// States which mouse button press should be detected
/// </summary>
public static readonly DependencyProperty MouseButtonProperty =
DependencyProperty.RegisterAttached(
"MouseButton",
typeof(MouseButtonType),
typeof(MouseDownWait),
new PropertyMetadata(
(o, e) =>
{
var ctrl = o as UIElement;
if (ctrl != null)
{
new MouseDownWait(ctrl);
}
}));
/// <summary>
/// The time (in milliseconds) to wait before detecting mouse press
/// </summary>
public static readonly DependencyProperty TimeProperty = DependencyProperty.RegisterAttached(
"Time", typeof(int), typeof(MouseDownWait), new FrameworkPropertyMetadata(0, OnTimePropertyChanged));
/// <summary>
/// Method to be called when the mouse press is detected
/// </summary>
public static readonly DependencyProperty DetectMethodProperty =
DependencyProperty.RegisterAttached(
"DetectMethod",
typeof(string),
typeof(MouseDownWait));
/// <summary>
/// Target object for the method calls (if not the datacontext)
/// </summary>
public static readonly DependencyProperty MethodTargetProperty =
DependencyProperty.RegisterAttached("MethodTarget", typeof(object), typeof(MouseDownWait));
/// <summary>
/// The timer used to detect mouse button holds
/// </summary>
private static readonly DispatcherTimer Timer = new DispatcherTimer();
/// <summary>
/// The element containing the attached property
/// </summary>
private readonly UIElement element;
/// <summary>
/// Initializes a new instance of the <see cref="MouseDownWait"/> class.
/// </summary>
/// <param name="element">The element.</param>
public MouseDownWait(UIElement element)
{
this.element = element;
if (this.element == null)
{
return;
}
this.element.MouseLeftButtonDown += ElementMouseLeftButtonDown;
this.element.MouseLeftButtonUp += ElementMouseLeftButtonUp;
this.element.MouseRightButtonDown += ElementMouseRightButtonDown;
this.element.MouseRightButtonUp += ElementMouseRightButtonUp;
this.element.MouseDown += ElementMouseDown;
this.element.MouseUp += ElementMouseUp;
Timer.Tick += this.TimerTick;
}
/// <summary>
/// Gets the mouse button type
/// </summary>
/// <param name="element">The element.</param>
/// <returns>
/// The mouse button type
/// </returns>
public static MouseButtonType GetMouseButton(UIElement element)
{
return (MouseButtonType)element.GetValue(MouseButtonProperty);
}
/// <summary>
/// Sets the mouse button type
/// </summary>
/// <param name="element">The element.</param>
/// <param name="value">The type of mouse button</param>
public static void SetMouseButton(UIElement element, MouseButtonType value)
{
element.SetValue(MouseButtonProperty, value);
}
/// <summary>
/// Gets the time.
/// </summary>
/// <param name="element">The element.</param>
/// <returns>The time in milliseconds</returns>
public static int GetTime(UIElement element)
{
return (int)element.GetValue(TimeProperty);
}
/// <summary>
/// Sets the time.
/// </summary>
/// <param name="element">The element.</param>
/// <param name="value">The value.</param>
public static void SetTime(UIElement element, int value)
{
element.SetValue(TimeProperty, value);
}
/// <summary>
/// Sets the detect method
/// </summary>
/// <param name="element">The element.</param>
/// <param name="value">The value.</param>
public static void SetDetectMethod(UIElement element, string value)
{
element.SetValue(DetectMethodProperty, value);
}
/// <summary>
/// Gets the detect method
/// </summary>
/// <param name="element">The element.</param>
/// <returns>method name</returns>
public static string GetDetectMethod(UIElement element)
{
return (string)element.GetValue(DetectMethodProperty);
}
/// <summary>
/// Gets the method target.
/// </summary>
/// <param name="ctrl">The CTRL .</param>
/// <returns>method target (i.e. viewmodel)</returns>
public static object GetMethodTarget(UIElement ctrl)
{
var result = ctrl.GetValue(MethodTargetProperty);
if (result == null)
{
var fe = ctrl as FrameworkElement;
if (fe != null)
{
result = fe.DataContext;
}
}
return result;
}
/// <summary>
/// Sets the method target.
/// </summary>
/// <param name="ctrl">The CTRL .</param>
/// <param name="value">The value.</param>
public static void SetMethodTarget(UIElement ctrl, object value)
{
ctrl.SetValue(MethodTargetProperty, value);
}
/// <summary>
/// Called when the time property changes.
/// </summary>
/// <param name="d">The dependency object.</param>
/// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void OnTimePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Timer.Interval = TimeSpan.FromMilliseconds((int)e.NewValue);
}
/// <summary>
/// Called when a mouse down is detected
/// </summary>
private static void MouseDownDetected()
{
Timer.Start();
}
/// <summary>
/// Called when a mouse up is detected
/// </summary>
private static void MouseUpDetected()
{
Timer.Stop();
}
/// <summary>
/// Checks if the mouse button has been detected.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="type">The mouse button type.</param>
/// <param name="mouseDown">if set to <c>true</c> [mouse down].</param>
private static void CheckMouseDetected(object sender, MouseButtonType type, bool mouseDown)
{
var uiElement = sender as UIElement;
if (uiElement == null)
{
return;
}
if (GetMouseButton(uiElement) != type)
{
return;
}
if (mouseDown)
{
MouseDownDetected();
}
else
{
MouseUpDetected();
}
}
/// <summary>
/// Called when the mouse down event fires
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
private static void ElementMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
CheckMouseDetected(sender, MouseButtonType.Both, true);
}
/// <summary>
/// Called when the mouse up event fires
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
private static void ElementMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
CheckMouseDetected(sender, MouseButtonType.Both, false);
}
/// <summary>
/// Called when the left mouse down event fires
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
private static void ElementMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
CheckMouseDetected(sender, MouseButtonType.Left, true);
}
/// <summary>
/// Called when the left mouse up event fires
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
private static void ElementMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
CheckMouseDetected(sender, MouseButtonType.Left, false);
}
/// <summary>
/// Called when the right mouse down event fires
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
private static void ElementMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
CheckMouseDetected(sender, MouseButtonType.Right, true);
}
/// <summary>
/// Called when the right mouse up event fires
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
private static void ElementMouseRightButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
CheckMouseDetected(sender, MouseButtonType.Right, false);
}
/// <summary>
/// Called on each timer tick
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void TimerTick(object sender, EventArgs e)
{
Timer.Stop();
var method = GetDetectMethod(this.element);
if (!string.IsNullOrEmpty(method))
{
this.InvokeMethod(method);
}
}
/// <summary>
/// Invokes the method.
/// </summary>
/// <param name="methodName">Name of the method.</param>
/// <param name="parameters">The parameters.</param>
private void InvokeMethod(string methodName, params object[] parameters)
{
var target = GetMethodTarget(this.element);
var targetMethod = target.GetType().GetMethod(methodName);
if (targetMethod == null)
{
throw new MissingMethodException(methodName);
}
targetMethod.Invoke(target, parameters);
}
}
Uso:
<Border BorderBrush="Gray" BorderThickness="1" Height="200" Width="200" Background="Transparent"
local:MouseDownWait.MouseButton="Both"
local:MouseDownWait.Time="1000"
local:MouseDownWait.DetectMethod="MouseDetected">
<TextBlock x:Name="Title" HorizontalAlignment="Stretch" VerticalAlignment="Center" TextAlignment="Center" FontSize="28" />
</Border>
Esto llamar a un método en su DataContext (ViewModel) cuando el el tiempo especificado ha transcurrido. Puede detectar los botones izquierdo, derecho o ambos del mouse.
+1. Buena solución. Simplemente maneje el mango MouseLeave también con Timer.Stop(); –
@devdigital - Tengo un problema similar que estoy tratando de resolver con una pantalla sensible al tacto. Necesito filtrar los toques de los dedos que son causados por partes de la mano que pasan cerca de la pantalla y me gustaría intentar usar botones personalizados que detectan presiones ligeramente más largas. Parece que lo que está haciendo arriba podría funcionar, pero podría explicar cómo se integra este código en una aplicación. –
Si aplico la propiedad adjunta en varios controles, se disparan los diferentes métodos de Detección independientemente del control cliqueado, ¿es posible hacer que esto funcione como una instancia regular en lugar de estática? – MatiasK
- 1. ¿Ocultar elemento div con jQuery, cuando el mouse no se mueve durante un período de tiempo?
- 2. Android - Cómo contar el tiempo durante un largo período
- 3. Calcular las devoluciones durante el período de tiempo
- 4. Mata a un proceso de Javascript después de un período de tiempo establecido
- 5. Detener un hilo después de un cierto período de tiempo
- 6. Comprueba si una aplicación está inactiva durante un período de tiempo y la bloquea
- 7. ¿Se ejecuta una secuencia de comandos python durante un período de tiempo especificado por el usuario?
- 8. El controlador de medios Android muestra la pantalla durante un breve período de tiempo
- 9. Forzar el cierre de sesión de los usuarios si los usuarios están inactivos durante un cierto período de tiempo
- 10. ¿Cómo mostrar HTML al navegador de forma incremental durante un largo período de tiempo?
- 11. ¿Cuántas líneas de código se modificaron durante un período de tiempo?
- 12. Cómo esperar durante un período de tiempo después de ejecutar una función
- 13. tabla de bloqueo de SQL para un período de tiempo
- 14. VB Detecta el tiempo de inactividad
- 15. WPF RichTextBox sin ancho establecido
- 16. ¿Cómo ocultar un div después de un período de tiempo?
- 17. Use alarmManager y el servicio para realizar notificaciones de programación solo durante un período de tiempo específico
- 18. tiempo Joda, período de Millis total de
- 19. ¿Detecta el archivo Drag'n'Drop en WPF?
- 20. cola con elementos marcados con el tiempo dentro de un período de tiempo
- 21. Redirige el sitio web después de cierto período de tiempo
- 22. ¿Existe un buen algoritmo para verificar los cambios en los datos durante un período de tiempo específico?
- 23. SQL select & group por un período de tiempo (timestamp)
- 24. WPF Icono de mouse ocupado
- 25. Para aumentar el período de tiempo de espera
- 26. Contando días laborables regulares en un período de tiempo dado
- 27. ¿Cómo se agrupa DataFrame por un período de tiempo?
- 28. tiempo de espera establecido para una operación
- 29. Obtiene elemento (s) WPF bajo el mouse
- 30. Detecta y requiere un Windows QFE/parche durante la instalación
+1. También podría valer la pena considerar el uso de la clase StopWatch en lugar de registrar DateTime.Now, dependiendo de la precisión que se requiera. http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx –