C# 如何在 WPF FrameworkElement 上捕获单击和双击事件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2086213/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I catch both single-click and double-click events on WPF FrameworkElement?
提问by Edward Tanguay
I can catch a single-clickon a TextBlock like this:
我可以像这样单击TextBlock:
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("you single-clicked");
}
I can catch a double-clickon a TextBlock like this:
我可以像这样双击TextBlock:
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
if (e.ClickCount == 2)
{
MessageBox.Show("you double-clicked");
}
}
}
But how do I catch them both on a single TextBlock and differentiate between the two?
但是如何在单个 TextBlock 上捕获它们并区分两者?
回答by Kent Boogaart
If you need to detect the difference, I suggest you use a control such as Label
that does the work for you:
如果您需要检测差异,我建议您使用这样的控件Label
来为您工作:
label.MouseDown += delegate(object sender, MouseEventArgs e)
{
if (e.ClickCount == 1)
{
// single click
}
};
label.MouseDoubleClick += delegate
{
// double click
};
EDIT: My advice was following from documentation on MSDN:
编辑:我的建议来自 MSDN 上的文档:
The Control class defines the PreviewMouseDoubleClick and MouseDoubleClick events, but not corresponding single-click events. To see if the user has clicked the control once, handle the MouseDown event (or one of its counterparts) and check whether the ClickCount property value is 1.
Control 类定义了 PreviewMouseDoubleClick 和 MouseDoubleClick 事件,但不定义相应的单击事件。要查看用户是否单击过控件一次,请处理 MouseDown 事件(或其对应事件之一)并检查 ClickCount 属性值是否为 1。
However, doing so will give you a single click notification even if the user single clicks.
但是,即使用户单击,这样做也会给您一个单击通知。
回答by Natxo
You need to fire the event after the click sequence is over... when is that? I suggest using a timer. The MouseDown event would reset it and increase the click count. When timer interval elapses it makes the call to evaluate the click count.
您需要在点击序列结束后触发事件......那是什么时候?我建议使用计时器。MouseDown 事件将重置它并增加点击次数。当计时器间隔过去时,它会调用以评估点击次数。
private System.Timers.Timer ClickTimer;
private int ClickCounter;
public MyView()
{
ClickTimer = new Timer(300);
ClickTimer.Elapsed += new ElapsedEventHandler(EvaluateClicks);
InitializeComponent();
}
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
ClickTimer.Stop();
ClickCounter++;
ClickTimer.Start();
}
private void EvaluateClicks(object source, ElapsedEventArgs e)
{
ClickTimer.Stop();
// Evaluate ClickCounter here
ClickCounter = 0;
}
Cheers!
干杯!
回答by awe
You must use a timer to differentiate between the two. Add a timer to your form in the GUI (easiest that way - it will automatically handle disposing etc...). In my example, the timer is called clickTimer
.
您必须使用计时器来区分两者。在 GUI 中为您的表单添加一个计时器(最简单的方式 - 它会自动处理处理等......)。在我的示例中,计时器称为clickTimer
。
private bool mSingleClick;
private void TextBlock_MouseUp(object sender, MouseButtonEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (e.ClickCount < 2)
{
mSingleClick = true;
clickTimer.Interval = System.Windows.Forms.SystemInformation.DoubleClickTime;
clickTimer.Start();
}
else if (e.ClickCount == 2)
{
clickTimer.Stop();
mSingleClick = false;
MessageBox.Show("you double-clicked");
}
}
}
private void clickTimer_Tick(object sender, EventArgs e)
{
if (mSingleClick)
{
clickTimer.Stop();
mSingleClick = false;
MessageBox.Show("you single-clicked");
}
}
回答by Sebastien Pellizzari
You could do it on MouseUp instead of MouseDown. That way you can ask the ClickCount
property for the total number of clicks, and decide what to do from that point.
您可以在 MouseUp 而不是 MouseDown 上执行此操作。这样您就可以向ClickCount
媒体询问总点击次数,然后决定从那时起做什么。
回答by Kamran
I did it this Way and it works perfectly
我是这样做的,而且效果很好
If e.Clicks = 2 Then
doubleClickTimer.Stop()
ElseIf e.Clicks = 1 Then
doubleClickTimer.Enabled = True
doubleClickTimer.Interval = 1000
doubleClickTimer.Start()
End If
Private Sub doubleClickTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles doubleClickTimer.Tick
OpenWebPage("abc")
doubleClickTimer.Stop()
End Sub
回答by AsfK
You are simply can use MouseDown
event and count click number, like this:
您可以简单地使用MouseDown
事件并计算点击次数,如下所示:
if (e.ChangedButton == MouseButton.Left && e.ClickCount == 2)
{
// your code here
}
回答by eMeL
It's my working solution :)
这是我的工作解决方案:)
#region message label click --------------------------------------------------------------------------
private Timer messageLabelClickTimer = null;
private void messageLabel_MouseUp(object sender, MouseButtonEventArgs e)
{
Debug.Print(e.ChangedButton.ToString() + " / Left:" + e.LeftButton.ToString() + " Right:" + e.RightButton.ToString() + " click: " + e.ClickCount.ToString());
// in MouseUp (e.ClickCount == 2) don't work!! Always 1 comes.
// in MouseDown is set e.ClickCount succesfully (but I don't know should I fire one clicked event or wait second click)
if (e.ChangedButton == MouseButton.Left)
{
if (messageLabelClickTimer == null)
{
messageLabelClickTimer = new Timer();
messageLabelClickTimer.Interval = 300;
messageLabelClickTimer.Elapsed += new ElapsedEventHandler(messageLabelClickTimer_Tick);
}
if (! messageLabelClickTimer.Enabled)
{ // Equal: (e.ClickCount == 1)
messageLabelClickTimer.Start();
}
else
{ // Equal: (e.ClickCount == 2)
messageLabelClickTimer.Stop();
var player = new SoundPlayer(ExtraResource.bip_3short); // Double clicked signal
player.Play();
}
}
}
private void messageLabelClickTimer_Tick(object sender, EventArgs e)
{ // single-clicked
messageLabelClickTimer.Stop();
var player = new SoundPlayer(ExtraResource.bip_1short); // Single clicked signal
player.Play();
}
#endregion
回答by CptCoathanger
My issue was with single/double-clicking rows in a DataGrid
in WPF
. For some reason the ButtonDown
events weren't firing, only the OnMouseLeftButtonUp
event was. Anyway, I wanted to handle the single-click differently from the double-click. It looks me a little time (I'm sure the solution isn't perfect, but it appears to work) to distill the problem down until I got it down to the below. I created a Task
which calls an Action
and that Action
's target can be updated by a second click. Hope this helps someone!
我的问题是在 a DataGrid
in 中单击/双击行WPF
。出于某种原因,ButtonDown
事件没有触发,只有OnMouseLeftButtonUp
事件触发了。无论如何,我想以不同于双击的方式处理单击。看起来我需要一点时间(我确定解决方案并不完美,但它似乎有效)来提炼问题,直到我将其归结为以下问题。我创建了一个Task
调用 anAction
并且它Action
的目标可以通过第二次点击更新。希望这对某人有帮助!
private Action _clickAction;
private int _clickCount;
private void Grid_OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("Button Click Occurred");
_clickCount++;
if (_clickCount == 1)
{
_clickAction = SingleClick;
}
if (_clickCount > 1)
{
_clickAction = DoubleClick;
}
if (_clickCount == 1)
{
Task.Delay(200)
.ContinueWith(t => _clickAction(), TaskScheduler.FromCurrentSynchronizationContext())
.ContinueWith(t => { _clickCount = 0; });
}
}
private void DoubleGridClick()
{
Debug.WriteLine("Double Click");
}
private void SingleGridClick()
{
Debug.WriteLine("Single Click");
}
回答by mike
My suggestion, implemented in a UserControl
by simply using a Task
:
我的建议,UserControl
通过简单地使用 a 实现Task
:
private int _clickCount = 0;
protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
{
_clickCount = e.ClickCount;
}
protected override async void OnPreviewMouseUp(MouseButtonEventArgs e)
{
if (_clickCount > 1)
{
//apparently a second mouse down event has fired => this must be the second mouse up event
//no need to start another task
//the first mouse up event will be handled after the task below
return;
}
await Task.Delay(500);
if (_clickCount == 1)
{
//single click
}
else
{
//double (or more) click
}
}
The drawback of all these solutions is, of course, that there will be a delay before actually responding to the user's action.
当然,所有这些解决方案的缺点是在实际响应用户操作之前会有延迟。