May
14th | 2008
Last week I was faced with a problem. I needed to implement a MouseDoubleClick Event on a WPF Grid. I said Ha, easy, but as i went on to implement it i realized that the Grid has no MouseDoubleClick Event! So how am I supposed to implement it? I came up with 2 solutions so here goes:
-
the first thought i had was to create a User Control that held only a grid and implement the MouseDoubleClick on the User Control itself so what you will get is this Xaml code:
-
I like This method better because it uses the power of WPF ControlTemplates. We need a WPF Grid with a MouseDoubleClick Event, which control has a MouseDoubleClick Event? a Button… So we want a Button that looks like a Grid. No problem all we need is to create a Style with Control Template to the Button:
<UserControl x:Class=”CustomDoubleClick.GridWrapper” xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation” xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml” Height=”300″ Width=”300″> <Grid> </Grid> </UserControl>
Since the Grid takes the entire space of the control if you implement a MouseDoubleClick event on the control:
public partial class GridWrapper : UserControl { public GridWrapper() { InitializeComponent(); this.MouseDoubleClick += new MouseButtonEventHandler(GridWrapper_MouseDoubleClick); } void GridWrapper_MouseDoubleClick(object sender, MouseButtonEventArgs e) { throw new NotImplementedException(); } }
What you got is a WPF Grid with a MouseDoubleClick Event.
<Window x:Class=”CustomDoubleClick.Window1″ xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation” xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml” xmlns:this=”clr-namespace:CustomDoubleClick” Title=”Window1″ Height=”300″ Width=”300″> <Window.Resources> <Style TargetType=”{x:Type Button}” x:Key=”GridButton”> <Setter Property=”Template”> <Setter.Value> <ControlTemplate> <Grid Background=”{TemplateBinding Property=Background}” Width=”{TemplateBinding Property=Width}” Height=”{TemplateBinding Property=Height}”> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </Window.Resources> <Canvas> <Button Style=”{StaticResource GridButton}” Width=”200″ Height=”200″ Background=”Red” MouseDoubleClick=”Button_MouseDoubleClick”> </Button> </Canvas> </Window>
And once again you get a Grid with a MouseDoubleClick Event. You can use this method to add double click to any WPF control in the toolbox.
Do you know of a different way to do this? If so, please comment.
Amit
By Derek Lakin on May 14, 2008 | Reply
You could just handle the MouseDown event for whichever control you have that doesn’t support double-clicks (like Grid) and check to see whether the ClickCount property in the MouseButtonEventArgs is 2 (or more if you like!):
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount >= 2)
{
// Do whatever you want in response to a double click.
}
}
Seems like a quicker and easier way to handle double-clicks
By Shahar Y on May 14, 2008 | Reply
Hi Derek Lakin,
That is really another great option to handle the problem. But the condition should be: if (e.ClickCount >= 2 && e.LeftButton == MouseButtonState.Pressed). Otherwise, right clicks and any other mouse clicks will count too.
Thanks.
By David N on May 14, 2008 | Reply
You can also do this by adding an InputBinding to the Grid, that will translate a double click to an invocation of a RoutedCommand, then you can bind that to some handler code somewhere higher in the tree. Commands seem to be a neglected part of WPF, but are really quite useful especially if there are multiple actions that should end up triggering the same code (button, toolbar button, context menu, key combination, double click in the grid..). I just used a builtin command in this sample but of course you’d probably use a custom one.
By Amit on May 15, 2008 | Reply
@ David
I will try you solution and if it works you will earn a big credit in my next post because it is a great solution. I use Commands all the time as they are so comfortable.
@ Derek
I am femiliar with your solution and have used it before, but it can give you a lot of trouble when you interop with WinForms. It also makes Debuging a bit hard because if you have a break point the second click will not be registered
Amit
By Michael H on Jul 21, 2008 | Reply
I have tried Derek’s approach on CheckBox and it didn’t work entirely.
First off the CheckBox is doing something with the Click Event so if you want to do a MouseUp or MouseDown it is ignored unless you do the PreviewMouseUp or PreviewMouseDown.
To add to Derek’s suggestion there is a MouseLeftButtonDown and MouseLeftButtonUp as well as a PreviewMouseLeftButtonDown and PreviewMouseLeftButtonUp so you don’t have to do the “IF” statement.
The problem exists in that you do a PreviewMouseDown or PreviewMouseUp and lets say you want the CheckBox to be checked when this happens. Once that code execution is completed and the Box is checked you will find that the CheckBoxes own Click event is fired and it will deselect the box.
You can override the CheckBox to get around this but it just seems like it is going too far to fix this problem… this should be easier.
PS one more comment. I noticed you are doing a e.ClickCount == 2. In my opinion this should be done on MouseUp and not on the MouseDown event however if you were to try this you would find that the ClickCount is not populated correctly on the MouseUp. I am finding many little things like this frustrating about the whole WPF world.