WPF StackPanel with Click AND DoubleClick
<StackPanel MouseDown="StackPanel_MouseDown"> <!--stackpanel content--> <TextBlock>Hello</TextBlock></StackPanel>
Then in the event handler:
private void StackPanel_MouseDown(object sender, MouseButtonEventArgs e) { if (e.ClickCount >= 2) { string hello; //only hit here on double click } }
Should work. Note that single clicking in the StackPanel would hit the event (but fail the if check)
...years later. @MoominTroll's solution is perfectly acceptable. Another option is to wrap the stack panel in a content control that supports the double click event.
<ContentControl MouseDoubleClick="DoubleClickHandler" > <StackPanel> </StackPanel></ContentControl>
The best way is to write your own mouse button handler with a timeout - if the event is fired again within the timeout period, then fire your doubleclick message, otherwise call the single click handler. Here's some sample code (Edit: originally found 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); } }}
Then, in the control you want to receive the events:
MouseClickManager fMouseManager = new MouseClickManager(200);fMouseManager.Click += new MouseButtonEventHandler(YourControl_Click); fMouseManager.DoubleClick += new MouseButtonEventHandler(YourControl_DoubleClick);