Самый чистый одиночный щелчок + обработка двойного щелчка в Silverlight?

Я находил различные методы работы с двойным щелчком, а затем авторы добавляли некоторый код if для обработки одиночных щелчков. Есть ли стандарт в Silverlight 3, который все используют для обработки как одиночного, так и двойного щелчка по спискам?


person Josh    schedule 13.08.2009    source источник
comment
Меня очень раздражает тот факт, что двойной щелчок и правый щелчок должны быть хаком в Silverlight...   -  person Stilgar    schedule 14.08.2009
comment
Я согласен. Я вижу, где щелчок правой кнопкой мыши проблематичен, но я бы подумал, что двойной щелчок - это легко.   -  person Josh    schedule 14.08.2009


Ответы (6)


Если вы используете библиотеку Reactive Extensions (Rx), код для поддержки двойного клик намного проще:

Observable.FromEvent<MouseButtonEventArgs>(myControl, "MouseLeftButtonDown").TimeInterval().Subscribe(evt =>
        {
            if (evt.Interval.TotalMilliseconds <= 300)
            {
                // Do something on double click
            }
        });
person Flatliner DOA    schedule 21.01.2010
comment
На самом деле это неправильно, хотя и очень незначительно. Следует проверить Interval.TotalMilliseconds, потому что, если вы проверите только Interval.Milliseconds, двойной щелчок также будет через 2 часа, 3 минуты и 500 мс. - person Erik van Brakel; 27.01.2011
comment
Хороший улов, я исправил это. - person Flatliner DOA; 31.01.2011

Напишите один раз используйте легко ....

 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);
    }
}
}
person Davut Gürbüz    schedule 14.08.2012

Мне нравится такой подход: http://www.domagoj.pavlesic.com/DoubleClick-in-Silverlight

Плюсы: у вас есть отложенные события одиночного клика, двойного клика и одиночного клика (так что вы можете быть уверены, что двойного клика не будет).

person Alex S    schedule 24.01.2011

Я реализовал чистый способ регистрации для событий 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);           

        }
    }
 }
person Arthur Nunes    schedule 04.05.2012

В Silverlight 5 есть более простой способ, который поддерживает MouseButtonEventArgs.ClickCount. Итак, вы можете просто подключить обычный обработчик MouseLeftButtonDown и проверить:

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

    // handle double-click
}
person McGarnagle    schedule 10.04.2014

Вот класс, который я реализовал для элементов управления, а также второй производный класс ниже для древовидного представления (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

Конец класса

person Paully    schedule 20.08.2009