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:Class="LongPressButton.MainWindow"
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
Simple WPF: WPF 实现按钮的长按,短按功能的更多相关文章
- WPF实现Twitter按钮效果
最近上网看到这个CSS3实现的Twitter按钮,感觉很漂亮,于是想用WPF来实现下. 实现这个效果,参考了CSS3 原文地址:http://www.html5tricks.com/css3-twit ...
- WPF 带清除按钮的文字框SearchTextBox
原文:WPF 带清除按钮的文字框SearchTextBox 基于TextBox的带清除按钮的搜索框 样式部分: <!--带清除按钮文字框--> <Style TargetType=& ...
- WPF实现Twitter按钮效果(转)
最近上网看到这个CSS3实现的Twitter按钮,感觉很漂亮,于是想用WPF来实现下. 实现这个效果,参考了CSS3 原文地址:http://www.html5tricks.com/css3-twit ...
- 在VS2005中设置WPF中自定义按钮的事件
原文:在VS2005中设置WPF中自定义按钮的事件 上篇讲了如何在Blend中绘制圆角矩形(http://blog.csdn.net/johnsuna/archive/2007/08/13/17407 ...
- [原译]一步步教你制作WPF圆形玻璃按钮
原文:[原译]一步步教你制作WPF圆形玻璃按钮 图1 1.介绍 从我开始使用vista的时候,我就非常喜欢它的圆形玻璃按钮.WPF最好的一个方面就是允许自定义任何控件的样式.用了一段时间的Micros ...
- WPF中使用AxisAngleRotation3D实现CAD的2D旋转功能
原文:WPF中使用AxisAngleRotation3D实现CAD的2D旋转功能 对于CAD图形来说,3D旋转比较常用,具体实现方法在上篇文章<WPF中3D旋转的实现 >中做了 ...
- nginx 代理tcp长连接短连接配置
https://blog.csdn.net/tayinyinyueyue/article/details/78932697 nginx使用ngx_stream_core_module模块代理tcp长连 ...
- 长连接 短连接 RST报文
https://baike.baidu.com/item/短连接 短连接(short connnection)是相对于长连接而言的概念,指的是在数据传送过程中,只在需要发送数据时,才去建立一个连接,数 ...
- WPF学习笔记(2)——动画效果按钮变长
说明(2017-6-12 11:26:48): 1. 视频教程里是把一个按钮点击一下,慢慢变长: 注意几个方面: (1)RoutedEvent="Button.Click",这里面 ...
- WPF datagrid 列按钮使用
原文:WPF中使用DataGrid时操作列按钮问题 <DataGrid x:Name="datagrid" AutoGenerateColumns="Fal ...
随机推荐
- get pull报错 Please commit your changes or stash them before you merge
当本地分支和远程修改了同一个文件代码,pull远程分支的代码的时候会出现文件冲突 出现这个错误 Please commit your changes or stash them before you ...
- PyQt5自定义信号
一.简介 在 PyQt5 中,自定义信号是一个常见的任务,通常用于在对象之间传递信息或触发特定行为.自定义信号需要继承自 QtCore.pyqtSignal 并定义其参数类型. 二.操作步骤 1.导入 ...
- 我开源的H5商城2.0版本发布,强烈推荐
简介 waynboot-mall 是一套全部开源的 H5 商城项目,包含运营后台.H5 商城前台和后端接口三个项目 .实现了一套完整的商城业务,有首页展示.商品分类.商品详情.sku 详情.商品搜索. ...
- Kubernetes集群中配置Ingress支持HTTPS访问(一):cfssl
目录 一.系统环境 二.前言 三.对称加密和非对称加密简介 四.什么是HTTPS 五.Ingress简介 六.配置ingress对外发布服务 6.1 安装NGINX ingress controlle ...
- Git 出现 Permission denied 时,重新生成ssh密钥
1,右键本地仓库,点击 [ Git Bash Here] 出现如下对话框: 输入 ssh-keygen 然后一直回车,注意: 保存的SSH目录 在 C:\Users\xiaocj\.ssh ...
- 我对asp.net管道模型的理解
参考:http://www.tracefact.net/tech/001.htmlhttps://www.xuebuyuan.com/zh-hant/470245.html我们的web程序被iis启动 ...
- PHP 中使用 ElasticSearch 的最佳实践(上)
PHP 中使用 ElasticSearch 的最佳实践 引言 PHP 开发者其实使用到 ES 的情况并不多,因为开发的大多数项目可能都没有快速模糊搜索的需求. 即使有这样的需求,用 MySQL 的 l ...
- CSS操作——文本属性
1.font-style(字体样式风格) /* 属性值: normal:设置字体样式为正体.默认值. italic:设置字体样式为斜体.这是选择字体库中的斜体字. oblique:设置字体样式为斜体. ...
- 搭建内网yum仓库
服务器配置: 1. 创建yum仓库的目录,rpm包上传到这里. mkdir /soft/x86 -p 2. 修改yum缓存配置: sed -i 's#keepcache=0#keepcache=1#g ...
- NumPy 均匀分布模拟及 Seaborn 可视化教程
均匀分布 简介 均匀分布是一种连续概率分布,表示在指定范围内的所有事件具有相等的发生概率.它常用于模拟随机事件,例如生成随机数或选择随机样本. 参数 均匀分布用两个参数来定义: a:下限,表示分布的最 ...