我需要能夠處理雙擊和單擊事件在WPF StackPanel上。但是沒有StackPanel的DoubleClick事件。 我想在這2個EventHandlers中做2個不同的操作。WPF StackPanel with Click和DoubleClick
任何想法如何做到這一點?
謝謝
我需要能夠處理雙擊和單擊事件在WPF StackPanel上。但是沒有StackPanel的DoubleClick事件。 我想在這2個EventHandlers中做2個不同的操作。WPF StackPanel with Click和DoubleClick
任何想法如何做到這一點?
謝謝
,最好的辦法是右鍵一個超時自己的鼠標按鈕的處理程序 - 如果事件在超時時間內再次發射,再火的DoubleClick的消息,否則調用一次點擊處理程序。下面是一些示例代碼(編輯:最初發現here):
/// <summary>
/// For double clicks
/// </summary>
public class MouseClickManager {
private event MouseButtonEventHandler _click;
private event MouseButtonEventHandler _doubleClick;
public event MouseButtonEventHandler Click {
add { _click += value; }
remove { _click -= value; }
}
public event MouseButtonEventHandler DoubleClick {
add { _doubleClick += value; }
remove { _doubleClick -= value; }
}
/// <summary>
/// Gets or sets a value indicating whether this <see cref="MouseClickManager"/> is clicked.
/// </summary>
/// <value><c>true</c> if clicked; otherwise, <c>false</c>.</value>
private bool Clicked { get; set; }
/// <summary>
/// Gets or sets the timeout.
/// </summary>
/// <value>The timeout.</value>
public int DoubleClickTimeout { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="MouseClickManager"/> class.
/// </summary>
/// <param name="control">The control.</param>
public MouseClickManager(int doubleClickTimeout) {
this.Clicked = false;
this.DoubleClickTimeout = doubleClickTimeout;
}
/// <summary>
/// Handles the click.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
public void HandleClick(object sender, MouseButtonEventArgs e) {
lock (this) {
if (this.Clicked) {
this.Clicked = false;
OnDoubleClick(sender, e);
}
else {
this.Clicked = true;
ParameterizedThreadStart threadStart = new ParameterizedThreadStart(ResetThread);
Thread thread = new Thread(threadStart);
thread.Start(e);
}
}
}
/// <summary>
/// Resets the thread.
/// </summary>
/// <param name="state">The state.</param>
private void ResetThread(object state) {
Thread.Sleep(this.DoubleClickTimeout);
lock (this) {
if (this.Clicked) {
this.Clicked = false;
OnClick(this, (MouseButtonEventArgs)state);
}
}
}
/// <summary>
/// Called when [click].
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
private void OnClick(object sender, MouseButtonEventArgs e) {
if (_click != null) {
if (sender is Control) {
(sender as Control).Dispatcher.BeginInvoke(_click, sender, e);
}
}
}
/// <summary>
/// Called when [double click].
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
private void OnDoubleClick(object sender, MouseButtonEventArgs e) {
if (_doubleClick != null) {
_doubleClick(sender, e);
}
}
}
然後,在控制要接收的事件:
MouseClickManager fMouseManager = new MouseClickManager(200);
fMouseManager.Click += new MouseButtonEventHandler(YourControl_Click);
fMouseManager.DoubleClick += new MouseButtonEventHandler(YourControl_DoubleClick);
+1 - 比我的回答全面十億倍 – MoominTroll 2009-11-30 17:15:38
@MoominTroll哈哈,恰好我剛剛在我們的應用程序中實現了這個功能:D – 2009-11-30 17:17:23
我必須讀錯了......每當你開始一個新的線程鼠標點擊,它不是一個雙擊?哇...那是......哼哼......特別的。 請使用「e.ClickCount> = 2」考慮下面的解決方案。 – joce 2010-04-12 19:37:21
<StackPanel MouseDown="StackPanel_MouseDown">
<!--stackpanel content-->
<TextBlock>Hello</TextBlock>
</StackPanel>
然後在事件處理程序:
private void StackPanel_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount >= 2)
{
string hello; //only hit here on double click
}
}
應該工作。請注意,單擊StackPanel會觸發事件(但如果檢查失敗)
不如處理雙擊事件的性能,但速度不夠快。 +1 – Randolpho 2009-11-30 17:16:11
是的我已經嘗試過..但我需要處理Single和DoubleClick .. clickcount並沒有真正的幫助,因爲它似乎也是doubleclick == singleclick。 – 2009-11-30 17:22:00
@ PaN1C_Showt1Me如何處理'if(e.ClickCount> = 2){HandleDoubelClick(); } else if(e.ClickCount> = 1){HandleSingleClick();}' – joce 2010-04-12 19:40:57
另一種方法是將MouseBinding添加到StackElement上的InputBindings,然後添加由MouseBinding激活的CommandBinding。總體而言,這比基於事件的機制更好,因爲它避免了由強引用引起的內存泄漏問題。它還提供了從表示中分離命令邏輯。
這就是說,它不那麼直接,並附加到事件使得一個偉大的捷徑。
不言而喻,讓你的堆棧面板背景至少是透明的,或者當你點擊「背景」時它不會被鼠標點擊測試捕獲。命中檢測跳過空背景。
我有類似的問題(響應單擊事件,並在雙擊事件的情況下做一個額外的工作)。我解決了這個問題是這樣的:
1)定義和聲明一些整數舉行最後點擊時間戳
int lastClickTimestamp;
2)Window_Loaded方法初始化先前聲明的變量與一些數量大於200
lastClickTimestamp = 1000;
3)鼠標按鈕的處理程序添加到堆棧面板
stackPanel.MouseLeftButtonUp += new MouseButtonEventHandler(stackPanel_MouseLeftButtonUp);
4)添加以下方法
void stackPanel_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (e.Timestamp - lastClickTimeStamp < 200)
{
//double click
}
lastClickTimeStamp = e.Timestamp;
//single click
}
如果您需要單獨檢測單擊和雙擊事件,則此代碼無用。這種情況會帶來更多複雜性,但可以毫無疑問地得到解決。
使用WPF的完整答案DispatcherTimer
。我們按需創建定時器,並在完成時斷開連接,以防止資源堵塞。
的C#:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
public partial class MainWindow : Window
{
DispatcherTimer dt;
bool clear_timer()
{
if (dt == null)
return false;
dt.Tick -= _single_click;
dt = null;
return true;
}
private void _click(Object sender, MouseButtonEventArgs e)
{
if (clear_timer())
Debug.Print("double click");
else
dt = new DispatcherTimer(
TimeSpan.FromMilliseconds(GetDoubleClickTime()),
DispatcherPriority.Normal,
_single_click,
Dispatcher);
}
void _single_click(Object sender, EventArgs e)
{
clear_timer();
Debug.Print("single click");
}
public MainWindow() { InitializeComponent(); }
[DllImport("user32.dll")]
static extern uint GetDoubleClickTime();
};
的XAML:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Orientation="Horizontal"
Background="AliceBlue"
Width="100"
Height="100"
MouseLeftButtonDown="_click" />
</Window>
...年以後。 @ MoominTroll的解決方案完全可以接受。另一種選擇是將堆棧面板包裝在支持雙擊事件的內容控件中。
<ContentControl MouseDoubleClick="DoubleClickHandler" >
<StackPanel>
</StackPanel>
</ContentControl>
有一個更簡單的解決方案來做到這一點。
在StackPanel中的事件PreviewMouseLeftDown(例如),您可以檢查是否MouseButtonEventArgs.ClickCount酒店的2 1 =單次點擊 2 =雙擊值
我仍然無法理解微軟怎麼可能人省略這樣的基本功能。 – 2013-01-11 19:41:28