防止双击双击命令

Jos*_*h G 13 .net c# wpf double-click

鉴于您有一个触发命令的控件:

<Button Command="New"/>
Run Code Online (Sandbox Code Playgroud)

如果用户双击命令,有没有办法阻止命令被触发两次?

编辑:在这种情况下重要的是我在WPF中使用命令模型.

看来按下按钮时,执行命令.除了禁用或隐藏按钮之外,我没有看到任何阻止这种情况的方法.

JDe*_*nis 16

由vidalsasoon提交的这个问题的检查答案是错误的,并且对于提出同样问题的各种方式都是错误的.

包含需要大量处理时间的代码的任何事件处理程序都可能导致延迟禁用所讨论的按钮; 无论在处理程序中调用禁用代码行的位置如何.

尝试下面的证明,您将看到禁用/启用与事件注册无关.按钮单击事件仍然已注册,仍在处理中.

矛盾证明1

private int _count = 0;

private void btnStart_Click(object sender, EventArgs e)
{
    btnStart.Enabled = false;

    _count++;
    label1.Text = _count.ToString();

    while (_count < 10)
    {            
        btnStart_Click(sender, e);            
    }           

    btnStart.Enabled = true;

}
Run Code Online (Sandbox Code Playgroud)

抗辩证明2

private void form1_load(object sender, EventArgs e)
{
    btnTest.Enabled = false;
}

private void btnStart_Click(object sender, EventArgs e)
{
    btnTest.Enabled = false;

    btnTest_click(sender, e);

    btnTest_click(sender, e);

    btnTest_click(sender, e);

    btnTest.Enabled = true;

}

private int _count = 0;

private void btnTest_click(object sender, EventArgs e)
{
    _count++;
    label1.Text = _count.ToString();
}
Run Code Online (Sandbox Code Playgroud)

  • @vidalsasoon你使用Winforms作为演示是正确的.然而,它们的关键点是事件注册与其他控件/按钮隔离启用或禁用属性,禁用按钮不会阻止订阅事件处理程序执行代码.这适用于WPF和Winforms.我只是想指出这篇文章的检查答案是不正确的.没有违法行为.我自己弄错了. (2认同)

Jon*_*ann 11

简单有效地阻止双击,三击和四击

<Button PreviewMouseDown="Button_PreviewMouseDown"/>

private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    if (e.ClickCount >= 2)
    {
        e.Handled = true;
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 10

我有同样的问题,这对我有用:

<Button>
    <Button.InputBindings>
            <MouseBinding Gesture="LeftClick" Command="New" />
    </Button.InputBindings>
</Button>
Run Code Online (Sandbox Code Playgroud)


JMa*_*sch 5

假设 WPF Commanding 没有给您足够的控制权来干扰单击处理程序,您能否在命令处理程序中放置一些代码来记住上次执行命令的时间并在给定时间段内请求时退出?(下面的代码示例)

这个想法是,如果是双击,您将在几毫秒内收到该事件两次,因此忽略第二个事件。

类似的东西:(在命令中)


// warning:  I haven't tried compiling this, but it should be pretty close
DateTime LastInvoked = DateTime.MinDate;
Timespan InvokeDelay = Timespan.FromMilliseconds(100);
{
  if(DateTime.Now - LastInvoked <= InvokeDelay)
     return;

  // do your work
}

(注意:如果它只是一个普通的旧点击处理程序,我会说遵循以下建议:http : //blogs.msdn.com/oldnewthing/archive/2009/04/29/9574643.aspx


sto*_*eur 5

您可以使用MVVMLightToolkit 中EventToCommand类来防止这种情况。

处理 Click 事件并将其EventToCommand从您的视图发送到您的视图模型(您可以使用它EventTrigger来执行此操作)。在您的视图中
设置并MustToggleIsEnabled="True"在您的视图模型中实现一个CanExecute()方法。
设置CanExecute()为在命令开始执行时返回 false,并在命令完成时返回 true。

这将在处理命令期间禁用该按钮。

  • 您所说的要点:如果按钮绑定到命令,请禁用该命令 (CanExecute() = false),直到该命令完成处理。 (2认同)

Rob*_*ney 5

您会认为这就像在命令运行时使用 aCommandCanExecute()返回 false一样简单。你错了。即使你CanExecuteChanged明确提出:

public class TestCommand : ICommand
{
    public void Execute(object parameter)
    {
        _CanExecute = false;
        OnCanExecuteChanged();
        Thread.Sleep(1000);
        Console.WriteLine("Executed TestCommand.");
        _CanExecute = true;
        OnCanExecuteChanged();
    }

    private bool _CanExecute = true;

    public bool CanExecute(object parameter)
    {
        return _CanExecute;
    }

    private void OnCanExecuteChanged()
    {
        EventHandler h = CanExecuteChanged;
        if (h != null)
        {
            h(this, EventArgs.Empty);
        }
    }

    public event EventHandler CanExecuteChanged;
}
Run Code Online (Sandbox Code Playgroud)

我怀疑如果这个命令引用了窗口的Dispatcher,并Invoke在调用时使用OnCanExecuteChanged,它会起作用。

我可以想到几种方法来解决这个问题。JMarsch 的方法是:简单地跟踪何时Execute被调用,如果在最后几百毫秒内被调用,则不做任何事情就退出。

更健壮的方法可能是让Execute方法 start aBackgroundWorker进行实际处理,CanExecute返回(!BackgroundWorker.IsBusy)CanExecuteChanged在任务完成时提升。该按钮应CanExecute()Execute()返回后立即重新查询,它会立即执行。


Joh*_*nks 5

我们像这样解决了...用异步我们找不到任何其他方法来有效阻止调用此Click的按钮上的额外点击:

private SemaphoreSlim _lockMoveButton = new SemaphoreSlim(1);
private async void btnMove_Click(object sender, RoutedEventArgs e)
{
    var button = sender as Button;
    if (_lockMoveButton.Wait(0) && button != null)
    {
        try
        {                    
            button.IsEnabled = false;
        }
        finally
        {
            _lockMoveButton.Release();
            button.IsEnabled = true;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 在尝试了本次和其他讨论中提到的所有方法后,这是我的 MVVM 项目中唯一对我有用的方法 (2认同)

Nat*_*oop 4

你可以设置一个标志

bool boolClicked = false;
button_OnClick
{
    if(!boolClicked)
    {
        boolClicked = true;
        //do something
        boolClicked = false;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我会添加一个 Try{ boolClicked = true; 做一点事(); 最后{ boolClicked = false;} 确保重置标志。干杯。 (3认同)