最后没有收到与计时器无关的解决方案的建议(我也没有找到任何建议),所以这里是一个简单的例子,如何在发生双击时防止单击。
Xaml:
<Window x:Class="StackOverflow.DoubleClickExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="100" Width="150"
MouseDown="RootElement_OnMouseDown">
</Window>
代码隐藏:
namespace StackOverflow.DoubleClickExample
{
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
public partial class MainWindow : Window
{
[DllImport("user32.dll")]
public static extern uint GetDoubleClickTime();
public MainWindow()
{
this.InitializeComponent();
}
private Guid lastGuid = Guid.Empty;
private void RootElement_OnMouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 1)
{
// Create new unique id and save it into field.
var guid = Guid.NewGuid();
this.lastGuid = guid;
// Run task asynchronously for ensuring that there is no another click
// happened in time interval when double-click can occure.
Task.Run(async () =>
{
// Wait system double-click time interval.
await Task.Delay((int)GetDoubleClickTime());
// If no double-click occured in awaited time interval, then
// last saved id (saved when first click occured) will be unchanged.
if (guid == this.lastGuid)
{
// Here is any logic for single-click handling.
Trace.WriteLine("Single-click occured");
}
});
return;
}
// Can be here only when e.ClickCount > 1, so must change last saved unique id.
// After that, asynchronously running task (for single-click) will detect
// that id was changed and so will NOT run single-click logic.
this.lastGuid = Guid.NewGuid();
// Here is any logic for double-click handling.
Trace.WriteLine("Double-click occured");
}
}
}
为了进行测试,请在窗口区域中单击并跟踪写入到 Visual Studio 输出窗口中的消息(菜单视图 -> 输出)。
另一种方法是使用CancellationTokenSource 并在发生双击时触发其Cancel 方法。只需替换lastGuid 字段和RootElement_OnMouseDown 方法:
private CancellationTokenSource cancellationTokenSource;
private void RootElement_OnMouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 1)
{
try
{
this.cancellationTokenSource = new CancellationTokenSource();
var token = this.cancellationTokenSource.Token;
// Run task asynchronously for ensuring that there is no another click
// happened in time interval when double-click can occure.
Task.Run(async () =>
{
// Wait system double-click time interval.
await Task.Delay((int)GetDoubleClickTime(), token);
// Here is any logic for single-click handling.
Trace.WriteLine("Single-click occured");
}, token);
}
catch (OperationCanceledException)
{
// This exception always occure when task is cancelled.
// It happening by design, just ignore it.
}
return;
}
// Cancel single-click task.
if (this.cancellationTokenSource != null)
{
this.cancellationTokenSource.Cancel();
}
// Here is any logic for double-click handling.
Trace.WriteLine("Double-click occured");
}