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)
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)
假设 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)
您可以使用MVVMLightToolkit 中的EventToCommand
类来防止这种情况。
处理 Click 事件并将其EventToCommand
从您的视图发送到您的视图模型(您可以使用它EventTrigger
来执行此操作)。在您的视图中
设置并MustToggleIsEnabled="True"
在您的视图模型中实现一个CanExecute()
方法。
设置CanExecute()
为在命令开始执行时返回 false,并在命令完成时返回 true。
这将在处理命令期间禁用该按钮。
您会认为这就像在命令运行时使用 aCommand
并CanExecute()
返回 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()
返回后立即重新查询,它会立即执行。
我们像这样解决了...用异步我们找不到任何其他方法来有效阻止调用此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)
你可以设置一个标志
bool boolClicked = false;
button_OnClick
{
if(!boolClicked)
{
boolClicked = true;
//do something
boolClicked = false;
}
}
Run Code Online (Sandbox Code Playgroud)