经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » ASP.net » 查看文章
Simple WPF: WPF 实现按钮的长按,短按功能
来源:cnblogs  作者:mrchip  时间:2024/7/8 9:54:27  对本文有异议

最新内容优先发布于个人博客:小虎技术分享站,随后逐步搬运到博客园。

实现了一个支持长短按得按钮组件,单击可以触发Click事件,长按可以触发LongPressed事件,长按松开时触发LongClick事件。源码请自取:Github

长按阈值属性的建立

为了方便在xaml中使用,我们先配置一个DependencyProperty叫做LongPressTime来作为界定长按的阈值

  1. public class LongPressButtonEx : Button
  2. {
  3. public static readonly DependencyProperty LongPressTimeProperty
  4. = DependencyProperty.Register("LongPressTime", typeof(int),
  5. typeof(LongPressButtonEx), new PropertyMetadata(500));
  6. public int LongPressTime
  7. {
  8. set => SetValue(LongPressTimeProperty, value);
  9. get => (int)GetValue(LongPressTimeProperty);
  10. }
  11. }

定义完成后可以在Xaml设计器中使用LongPressTime这个拓展属性

  1. <Window x:Class="LongPressButton.MainWindow"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6. xmlns:local="clr-namespace:LongPressButton"
  7. mc:Ignorable="d"
  8. Title="MainWindow" Height="450" Width="800">
  9. <Grid>
  10. <local:LongPressButtonEx Width="96" Height="48" LongPressTime="200">
  11. Button
  12. </local:LongPressButtonEx>
  13. </Grid>
  14. </Window>

长按的定时器判定方法

C#中的4种定时器,在WPF中需要使用Dispater Timer

定义一个DispatcherTimer来监控是否按下达到了长按

  1. private DispatcherTimer _pressDispatcherTimer;
  2. private void OnDispatcherTimeOut(object sender, EventArgs e)
  3. {
  4. _pressDispatcherTimer?.Stop();
  5. Debug.WriteLine($"Timeout {LongPressTime}");
  6. }
  7. protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
  8. {
  9. base.OnMouseLeftButtonDown(e);
  10. Debug.WriteLine("Button: Mouse down.");
  11. if (_pressDispatcherTimer == null)
  12. {
  13. _pressDispatcherTimer = new DispatcherTimer();
  14. _pressDispatcherTimer.Tick += OnDispatcherTimeOut;
  15. _pressDispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, LongPressTime);
  16. _pressDispatcherTimer.Start();
  17. Debug.WriteLine("Button: Timer started");
  18. }
  19. }
  20. protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
  21. {
  22. base.OnMouseLeftButtonUp(e);
  23. Debug.WriteLine("Button: Mouse up.");
  24. _pressDispatcherTimer?.Stop();
  25. _pressDispatcherTimer = null;
  26. }

现在分别点击和长按按钮可以看到调试输出

  1. ...
  2. # 点击
  3. Button: Mouse down.
  4. Button: Timer started
  5. Button: Mouse up.
  6. # 长按
  7. Button: Mouse down.
  8. Button: Timer started
  9. Timeout 200
  10. Button: Mouse up.

实现长按事件的定义

现在作为一个自定义控件,我们需要在长按后发出一个RoutedEvent,并修改部分之前的代码抛出事件

  1. /// <summary>
  2. /// LongPress Routed Event
  3. /// </summary>
  4. public static readonly RoutedEvent LongPressEvent
  5. = EventManager.RegisterRoutedEvent("LongPress",
  6. RoutingStrategy.Bubble,
  7. typeof(RoutedEventHandler),
  8. typeof(LongPressButtonEx));
  9. public event RoutedEventHandler LongPress
  10. {
  11. add => AddHandler(LongPressEvent, value);
  12. remove => RemoveHandler(LongPressEvent, value);
  13. }
  14. private void OnDispatcherTimeOut(object sender, EventArgs e)
  15. {
  16. _pressDispatcherTimer?.Stop();
  17. Debug.WriteLine($"Timeout {LongPressTime}");
  18. RaiseEvent(new RoutedEventArgs(LongPressEvent)); // raise the long press event
  19. }

回到窗体的代码中,添加事件的响应

  1. <local:LongPressButtonEx Height="48" Width="256" LongPressTime="200"
  2. LongPress="LongPressButtonEx_LongPress"
  3. Click="LongPressButtonEx_Click">
  4. Click or Long Press Me!
  5. </local:LongPressButtonEx>

C#代码如下,长按按钮会显示Long Pressed,单击会是Click

  1. private void LongPressButtonEx_LongPress(object sender, RoutedEventArgs e)
  2. {
  3. if (sender is LongPressButtonEx btn)
  4. {
  5. btn.Content = "Long Pressed";
  6. }
  7. }
  8. private void LongPressButtonEx_Click(object sender, RoutedEventArgs e)
  9. {
  10. if (sender is LongPressButtonEx btn)
  11. {
  12. btn.Content = "Clicked";
  13. }
  14. }

image

发现ClickLongPress都可以响应,但是当松开按钮时又变成了Click,原因是鼠标松开时响应了默认的Click事件

现在对按钮控件默认的OnClick函数稍作修改,可以让Click也不出问题

  1. /// <summary>
  2. /// DependencyProperty for IsLongPress
  3. /// </summary>
  4. public static readonly DependencyProperty IsLongPressProperty
  5. = DependencyProperty.Register("IsLongPress", typeof(bool),
  6. typeof(LongPressButtonEx), new PropertyMetadata(false));
  7. public bool IsLongPress
  8. {
  9. set => SetValue(IsLongPressProperty, value);
  10. get => (bool)GetValue(IsLongPressProperty);
  11. }
  12. private void OnDispatcherTimeOut(object sender, EventArgs e)
  13. {
  14. IsLongPress = true;
  15. _pressDispatcherTimer?.Stop();
  16. Debug.WriteLine($"Timeout {LongPressTime}");
  17. RaiseEvent(new RoutedEventArgs(LongPressEvent)); // raise the long press event
  18. }
  19. protected override void OnClick()
  20. {
  21. if (!IsLongPress)
  22. {
  23. base.OnClick();
  24. }
  25. else
  26. {
  27. RaiseEvent(new RoutedEventArgs(LongPressReleaseEvent)); // raise the long press event
  28. IsLongPress = false;
  29. }
  30. }

之后再进行点击操作,我们就可以看到符合预期的结果

image

长按+Style按钮的展示效果
外观Style自定义见这篇文章:WPF自定义按钮外形
image

参考链接

UIElement.MouseLeftButtonDown Event
用户控件自定义 DependencyProperty 属性使用教程
WPF 中 DispatcherTimer 计时器
如何:创建自定义路由事件
WPF 自定义带自定义参数路由事件
Use WPF Style in another assemble

原文链接:https://www.cnblogs.com/mrchip/p/18289007

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号