首页 > 其他分享 >Simple WPF: WPF 实现按钮的长按,短按功能

Simple WPF: WPF 实现按钮的长按,短按功能

时间:2024-07-08 09:09:19浏览次数:14  
标签:pressDispatcherTimer Simple LongPressTime Button 短按 Click WPF void

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

实现了一个支持长短按得按钮组件,单击可以触发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 onm ouseLeftButtonDown(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 onm ouseLeftButtonUp(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";
    }
}

image

发现ClickLongPress都可以响应,但是当松开按钮时又变成了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;
    }
}

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

image

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

参考链接

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

标签:pressDispatcherTimer,Simple,LongPressTime,Button,短按,Click,WPF,void
From: https://www.cnblogs.com/mrchip/p/18289007

相关文章

  • Halcon学习笔记(3):WPF 框架搭建,MaterialDesign+Prism
    目录前言环境Nuget安装新建WPF类库项目初始化PrismApp启动页初始化重写MainView前言其实我更喜欢CommunityToolkit.mvvm+HandyControl。但是因为找工作,你不能去抗拒新事物。这里就当体验一下完整的流程好了。环境windows11.netcore8.0Nuget安装新建WPF类库项目新......
  • Halcon 学习笔记(2):Halcon+WPF导入
    目录前言.netcore8.0.netcore8.0新功能,打开文件夹和打开文件HSmartWindowControlWPFSystem.Drawing.Common重置拉伸关闭拖拽和缩放文件导出前言这里补充一下Halcon导入到WPF的要求.netcore8.0Halcon是支持.netcore8.0导入的.netcore8.0新功能,打开文件夹和打开文件......
  • Simple WPF: WPF 自定义按钮外形
    最新内容优先发布于个人博客:小虎技术分享站,随后逐步搬运到博客园。WPF的按钮提供了Template模板,可以通过修改Template模板中的内容对按钮的样式进行自定义,完整代码Github自取。使用Style定义扁平化的按钮样式定义一个ButtonStyleDictonary.xaml资源字典文件,在ControlTemplate......
  • WPF Behavior InvokeCommandAction Command CommandParameter
    //xaml<behavior:Interaction.Triggers><behavior:EventTriggerEventName="MouseWheel"SourceObject="{BindingElementName=img}"><behavior:InvokeCommandActionCommand="{BindingMouseWheelCmd}"......
  • WPF常见控件(包含materialDesign)与属性
    materialDesign:ColorZone:用于在应用界面中创建有色区域,增加层级感和视觉吸引力。materialDesign:DrawerHost:用于实现从屏幕一侧滑出的抽屉控件,经常与materialDesign:DrawerHost.LeftDrawerContent配套使用(这里的例子是设置左抽屉)。DockPanel:布局控件,用于将其子元素排列在特......
  • WPF single instance via mutex
    usingSystem;usingSystem.Collections.Generic;usingSystem.Configuration;usingSystem.Data;usingSystem.Diagnostics.Eventing.Reader;usingSystem.Linq;usingSystem.Runtime.InteropServices;usingSystem.Threading;usingSystem.Threading.Tasks;usingS......
  • WPF MenuItem behavior MVVM
    //xaml<ImageGrid.Column="1"ClipToBounds="True"Source="{BindingSelectedItem.ImgUrl,ElementName=lbx}"><Image.ContextMenu><ContextMenu><MenuItemHeader="S......
  • 基于Linux/ARM/单片机利用状态机对多个按键进行扫描实现短按或者长按
    1)Linux/ARM/单片机入门级按键扫描程序设计,分享给将要学习或者正在学习Linux/ARM/单片机开发的同学。2)内容属于原创,若转载,请说明出处。3)提供相关问题有偿答疑和支持。学习Linux/ARM/单片机的同学都会学习到一个知识点,就是按键扫描,本课题基于SigmaStar的平台SSC375芯片SOC详细......
  • WPF MVVM capture window keyboard
    //xaml<behavior:Interaction.Triggers><behavior:EventTriggerEventName="KeyDown"><behavior:CallMethodActionTargetObject="{Binding}"MethodName="Window_KeyDown"/></beha......
  • WPF自定义控件与样式-自定义按钮(Button)
    一、前言程序界面上的按钮多种多样,常用的就这几种:普通按钮、图标按钮、文字按钮、图片文字混合按钮。本文章记录了不同样式类型的按钮实现方法。二、固定样式的按钮固定样式的按钮一般在临时使用时或程序的样式比较固定时才会使用,按钮整体样式不需要做大的改动。2.1普通按钮-......