using System; using System.Windows; using System.Windows.Input; namespace HandyControl.Tools; /// /// 输入层点击帮助类 /// public static class InputClickHelper { private static readonly DependencyProperty InputInfoProperty = DependencyProperty.RegisterAttached( "InputInfo", typeof(InputInfo), typeof(InputClickHelper), new PropertyMetadata(default(InputInfo))); private static void SetInputInfo(DependencyObject element, InputInfo value) => element.SetValue(InputInfoProperty, value); private static InputInfo GetInputInfo(DependencyObject element) => (InputInfo) element.GetValue(InputInfoProperty); /// /// 将 MouseDown MouseMove MouseUp 封装为点击事件 /// /// 要被附加的元素 /// 点击的事件 /// 因为拖动而结束点击时触发 public static void AttachMouseDownMoveUpToClick(UIElement element, EventHandler clickEventHandler, EventHandler dragStarted = null) { var inputInfo = GetOrCreateInputInfo(element); inputInfo.ClickEventHandler += clickEventHandler; inputInfo.DragStarted += dragStarted; element.MouseDown -= Element_MouseDown; element.MouseDown += Element_MouseDown; element.MouseMove -= Element_MouseMove; element.MouseMove += Element_MouseMove; element.MouseUp -= Element_MouseUp; element.MouseUp += Element_MouseUp; element.LostMouseCapture -= Element_LostMouseCapture; element.LostMouseCapture += Element_LostMouseCapture; } /// /// 去掉对 的点击时间的监听 /// /// /// 点击的事件 /// 因为拖动而结束点击时触发的事件 public static void DetachMouseDownMoveUpToClick(UIElement element, EventHandler clickEventHandler, EventHandler dragStarted = null) { var inputInfo = GetInputInfo(element); if (inputInfo == null) return; inputInfo.ClickEventHandler -= clickEventHandler; inputInfo.DragStarted -= dragStarted; if (inputInfo.IsEmpty()) { element.ClearValue(InputInfoProperty); element.MouseDown -= Element_MouseDown; element.MouseMove -= Element_MouseMove; element.MouseUp -= Element_MouseUp; element.LostMouseCapture -= Element_LostMouseCapture; } } private static void Element_LostMouseCapture(object sender, MouseEventArgs e) { var element = (UIElement) sender; GetInputInfo(element)?.LostCapture(); } private static void Element_MouseUp(object sender, MouseButtonEventArgs e) { var element = (UIElement) sender; GetInputInfo(element)?.Up(e.GetPosition(element)); } private static void Element_MouseMove(object sender, MouseEventArgs e) { var element = (UIElement) sender; GetInputInfo(element)?.Move(e.GetPosition(element)); } private static void Element_MouseDown(object sender, MouseButtonEventArgs e) { var element = (UIElement) sender; GetInputInfo(element)?.Down(e.GetPosition(element)); } private static InputInfo GetOrCreateInputInfo(UIElement element) { var inputInfo = GetInputInfo(element); if (inputInfo == null) { inputInfo = new InputInfo(); SetInputInfo(element, inputInfo); } return inputInfo; } private class InputInfo { private const double ToleranceSquared = 0.01; private Point _downedPosition; private bool _isClick; public event EventHandler ClickEventHandler; public event EventHandler DragStarted; public void Down(Point position) { _downedPosition = position; _isClick = true; } public void Move(Point position) { if (!_isClick) return; if ((position - _downedPosition).LengthSquared > ToleranceSquared) { _isClick = false; DragStarted?.Invoke(null, EventArgs.Empty); } } public void Up(Point position) { _isClick = _isClick && (position - _downedPosition).LengthSquared <= ToleranceSquared; if (!_isClick) return; ClickEventHandler?.Invoke(null, EventArgs.Empty); _isClick = false; } public void LostCapture() => _isClick = false; public bool IsEmpty() => ClickEventHandler is null && DragStarted is null; } }