Simple WPF: WPF 实现按钮的长按,短按功能
|
最新内容优先发布于个人博客:小虎技术分享站,随后逐步搬运到博客园。
实现了一个支持长短按得按钮组件,单击可以触发Click事件,长按可以触发LongPressed事件,长按松开时触发LongClick事件。源码请自取:Github
长按阈值属性的建立
为了方便在xaml中使用,我们先配置一个DependencyProperty叫做LongPressTime来作为界定长按的阈值- public class LongPressButtonEx : Button
- {
- public static readonly DependencyProperty LongPressTimeProperty
- = DependencyProperty.Register("LongPressTime", typeof(int),
- typeof(LongPressButtonEx), new PropertyMetadata(500));
- public int LongPressTime
- {
- set => SetValue(LongPressTimeProperty, value);
- get => (int)GetValue(LongPressTimeProperty);
- }
- }
复制代码 定义完成后可以在Xaml设计器中使用LongPressTime这个拓展属性- <Window x:
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:local="clr-namespace:LongPressButton"
- mc:Ignorable="d"
- Title="MainWindow" Height="450" Width="800">
- <Grid>
- <local:LongPressButtonEx Width="96" Height="48" LongPressTime="200">
- Button
- </local:LongPressButtonEx>
- </Grid>
- </Window>
复制代码 长按的定时器判定方法
C#中的4种定时器,在WPF中需要使用Dispater Timer
定义一个DispatcherTimer来监控是否按下达到了长按- private DispatcherTimer _pressDispatcherTimer;
- private void OnDispatcherTimeOut(object sender, EventArgs e)
- {
- _pressDispatcherTimer?.Stop();
- Debug.WriteLine($"Timeout {LongPressTime}");
- }
- protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
- {
- base.OnMouseLeftButtonDown(e);
- Debug.WriteLine("Button: Mouse down.");
- if (_pressDispatcherTimer == null)
- {
- _pressDispatcherTimer = new DispatcherTimer();
- _pressDispatcherTimer.Tick += OnDispatcherTimeOut;
- _pressDispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, LongPressTime);
- _pressDispatcherTimer.Start();
- Debug.WriteLine("Button: Timer started");
- }
- }
- protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
- {
- base.OnMouseLeftButtonUp(e);
- Debug.WriteLine("Button: Mouse up.");
- _pressDispatcherTimer?.Stop();
- _pressDispatcherTimer = null;
- }
复制代码 现在分别点击和长按按钮可以看到调试输出- ...
- # 点击
- Button: Mouse down.
- Button: Timer started
- Button: Mouse up.
- # 长按
- Button: Mouse down.
- Button: Timer started
- Timeout 200
- Button: Mouse up.
复制代码 实现长按事件的定义
现在作为一个自定义控件,我们需要在长按后发出一个RoutedEvent,并修改部分之前的代码抛出事件- /// <summary>
- /// LongPress Routed Event
- /// </summary>
- public static readonly RoutedEvent LongPressEvent
- = EventManager.RegisterRoutedEvent("LongPress",
- RoutingStrategy.Bubble,
- typeof(RoutedEventHandler),
- typeof(LongPressButtonEx));
- public event RoutedEventHandler LongPress
- {
- add => AddHandler(LongPressEvent, value);
- remove => RemoveHandler(LongPressEvent, value);
- }
- private void OnDispatcherTimeOut(object sender, EventArgs e)
- {
- _pressDispatcherTimer?.Stop();
- Debug.WriteLine($"Timeout {LongPressTime}");
- RaiseEvent(new RoutedEventArgs(LongPressEvent)); // raise the long press event
- }
复制代码 回到窗体的代码中,添加事件的响应- <local:LongPressButtonEx Height="48" Width="256" LongPressTime="200"
- LongPress="LongPressButtonEx_LongPress"
- Click="LongPressButtonEx_Click">
- Click or Long Press Me!
- </local:LongPressButtonEx>
复制代码 C#代码如下,长按按钮会显示Long Pressed,单击会是Click- private void LongPressButtonEx_LongPress(object sender, RoutedEventArgs e)
- {
- if (sender is LongPressButtonEx btn)
- {
- btn.Content = "Long Pressed";
- }
- }
- private void LongPressButtonEx_Click(object sender, RoutedEventArgs e)
- {
- if (sender is LongPressButtonEx btn)
- {
- btn.Content = "Clicked";
- }
- }
复制代码
发现Click和LongPress都可以响应,但是当松开按钮时又变成了Click,原因是鼠标松开时响应了默认的Click事件
现在对按钮控件默认的OnClick函数稍作修改,可以让Click也不出问题- /// <summary>
- /// DependencyProperty for IsLongPress
- /// </summary>
- public static readonly DependencyProperty IsLongPressProperty
- = DependencyProperty.Register("IsLongPress", typeof(bool),
- typeof(LongPressButtonEx), new PropertyMetadata(false));
- public bool IsLongPress
- {
- set => SetValue(IsLongPressProperty, value);
- get => (bool)GetValue(IsLongPressProperty);
- }
- private void OnDispatcherTimeOut(object sender, EventArgs e)
- {
- IsLongPress = true;
- _pressDispatcherTimer?.Stop();
- Debug.WriteLine($"Timeout {LongPressTime}");
- RaiseEvent(new RoutedEventArgs(LongPressEvent)); // raise the long press event
- }
- protected override void OnClick()
- {
- if (!IsLongPress)
- {
- base.OnClick();
- }
- else
- {
- RaiseEvent(new RoutedEventArgs(LongPressReleaseEvent)); // raise the long press event
- IsLongPress = false;
- }
- }
复制代码 之后再进行点击操作,我们就可以看到符合预期的结果
长按+Style按钮的展示效果
外观Style自定义见这篇文章:WPF自定义按钮外形
参考链接
UIElement.MouseLeftButtonDown Event
用户控件自定义 DependencyProperty 属性使用教程
WPF 中 DispatcherTimer 计时器
如何:创建自定义路由事件
WPF 自定义带自定义参数路由事件
Use WPF Style in another assemble
来源:https://www.cnblogs.com/mrchip/p/18289007
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|
|
|
发表于 2024-7-8 08:30:26
举报
回复
分享
|
|
|
|