You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF按钮长按延迟触发命令实现方案(支持XAML配置时长)

WPF实现长按触发命令的延迟按钮

WPF默认按钮点击会立即触发绑定的命令,为避免误触操作,我们可以实现一个自定义按钮,要求长按达到指定时长(如500毫秒或1秒)后才触发命令,同时支持在XAML中直接配置延迟时长。

感谢BionicCode的思路启发,经过修改后实现了可用的自定义控件,代码如下:

public class DelayButton : Button
{
    /// <summary>
    /// 延迟时长(毫秒)
    /// </summary>
    public int DelayInMilliseconds
    {
        get => (int)GetValue(DelayInMillisecondsProperty);
        set => SetValue(DelayInMillisecondsProperty, value);
    }

    public static readonly DependencyProperty DelayInMillisecondsProperty = DependencyProperty.Register(
      nameof(DelayInMilliseconds),
      typeof(int),
      typeof(DelayButton),
      new PropertyMetadata(0));

    /// <summary>
    /// 延迟触发命令
    /// </summary>
    public ICommand DelayCommand
    {
        get { return (ICommand)GetValue(DelayCommandProperty); }
        set { SetValue(DelayCommandProperty, value); }
    }

    public static readonly DependencyProperty DelayCommandProperty = DependencyProperty.Register("DelayCommand",
        typeof(ICommand),
        typeof(DelayButton),
        new PropertyMetadata(null));

    /// <summary>
    /// 取消令牌源
    /// </summary>
    private CancellationTokenSource? delayCancellationTokenSource;

    /// <summary>
    /// 触发有效性标记
    /// </summary>
    private bool isClickValid = false;


    /// <summary>
    /// 鼠标按下事件
    /// </summary>
    /// <param name="e"></param>
    protected override async void OnMouseLeftButtonDown(MouseButtonEventArgs e)
    {
        if (DelayInMilliseconds <= 0)
        {
            // 无延迟,立即触发
            this.isClickValid = true;
            DelayCommand?.Execute(this);
            return;
        }

        try
        {
            this.delayCancellationTokenSource = new CancellationTokenSource();

            await Task.Delay(TimeSpan.FromMilliseconds(this.DelayInMilliseconds), this.delayCancellationTokenSource.Token);

            // 检查鼠标仍处于按下状态且未触发过命令
            if (e.LeftButton is MouseButtonState.Pressed && !this.isClickValid)
            {
                this.isClickValid = true;
                DelayCommand?.Execute(this);
            }
        }
        catch (OperationCanceledException)
        {
            return;
        }
        finally
        {
            this.delayCancellationTokenSource?.Dispose();
            this.delayCancellationTokenSource = null;
        }
    }
    
    /// <summary>
    /// 鼠标抬起事件
    /// </summary>
    /// <param name="e"></param>
    protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
    {
        if (!this.isClickValid)
        {
            // 时长未达标,取消延迟任务
            this.delayCancellationTokenSource?.Cancel();
        }
        else
        {
            // 已触发命令,重置标记以便下次使用
            this.isClickValid = false;
        }
    }

    /// <summary>
    /// 鼠标离开事件
    /// </summary>
    /// <param name="e"></param>
    protected override void OnMouseLeave(MouseEventArgs e)
    {
        // 鼠标离开按钮,取消延迟任务
        this.delayCancellationTokenSource?.Cancel();
    }
}

使用示例

在XAML中直接引用该自定义按钮,配置延迟时长并绑定命令:

<Window xmlns:local="clr-namespace:YourNamespace">
    <local:DelayButton Content="长按1秒触发" 
                       DelayInMilliseconds="1000"
                       DelayCommand="{Binding YourCommand}" />
</Window>

内容的提问来源于stack exchange,提问作者ZhuYajun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 15:18:25