DataGrid Tips & Tricks: Single-Click Editing

By default, end users must double-click a cell in the DataGrid to enter edit mode. In certain cases, it may be more desirable for cells to enter edit mode with a single mouse click (for example, when editing a CheckBox). Use the code snippets below to implement single-click editing in your DataGrid.

To apply single-click editing to all cells in the DataGrid
1. Paste the style below into the Resources of your DataGrid
2. Paste the method into the code behind

To apply single-click editing to only certain cells in the DataGrid
1. Set an x:Key on the Style (ex. <Style x:Key="SingleClickEditing" TargetType="{x:Type dg:DataGridCell}">)
2. Paste the style into the Resources of your DataGrid
3. Apply the style to the CellStyle property of the columns which you'd like to have single click editing (ex. <dg:DataGridCheckBoxColumn CellStyle="{StaticResource SingleClickEditing}"/>)
4. Paste the method into the code behind

        <!--
          SINGLE CLICK EDITING
        -->
        <Style TargetType="{x:Type dg:DataGridCell}">
          <EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridCell_PreviewMouseLeftButtonDown"></EventSetter>
        </Style>

        //
        // SINGLE CLICK EDITING
        //
        private void DataGridCell_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            DataGridCell cell = sender as DataGridCell;
            if (cell != null && !cell.IsEditing && !cell.IsReadOnly)
            {
                if (!cell.IsFocused)
                {
                    cell.Focus();
                }
                DataGrid dataGrid = FindVisualParent<DataGrid>(cell);
                if (dataGrid != null)
                {
                    if (dataGrid.SelectionUnit != DataGridSelectionUnit.FullRow)
                    {
                        if (!cell.IsSelected)
                            cell.IsSelected = true;
                    }
                    else
                    {
                        DataGridRow row = FindVisualParent<DataGridRow>(cell);
                        if (row != null && !row.IsSelected)
                        {
                            row.IsSelected = true;
                        }
                    }
                }
            }
        }    

        static T FindVisualParent<T>(UIElement element) where T : UIElement
        {
            UIElement parent = element;
            while (parent != null)
            {
                T correctlyTyped = parent as T;
                if (correctlyTyped != null)
                {
                    return correctlyTyped;
                }

                parent = VisualTreeHelper.GetParent(parent) as UIElement;
            }
            return null;
        } 

Last edited Nov 13, 2008 at 12:42 PM by vinsibal, version 8

Comments

Soulfiremage Feb 18, 2013 at 4:37 PM 
Very handy, worked well. Thank you.

Twayleph Oct 9, 2012 at 7:14 PM 
Excellent solution, it solved my problems perfectly. Thanks for sharing !

replytoirfan Jul 10, 2012 at 1:24 PM 
Thanks vinsibal.

Woked code with one go.
Awsome article.

Irfan

SSSander Feb 16, 2012 at 11:39 PM 
Awesome!

Combined with the snippet in Wiki Link: [discussion:39284] a single click allows for acces to the items in a combo-box.

Thx for sharing

UncleMike Jan 28, 2011 at 9:54 AM 
This didn't work for me. Even after adding this code, I needed to click twice on a CheckBox to tick/untick it.

In the end, I developed this solution:
http://stackoverflow.com/questions/3833536/how-to-perform-single-click-checkbox-selection-in-wpf-datagrid/4827377#4827377

nalinjaya Dec 6, 2010 at 9:52 PM 
Thanks very much! Perfect solution for my requirement.

slakchana Oct 14, 2010 at 9:12 AM 
My datagrid SelectionUnit is FullRow. when is use the above code (by vinsibal) if (dataGrid != null) is always null. Please help me out

kartheesh Aug 17, 2010 at 12:43 PM 
Is there any way to add the style in code behind. Since i have create custom control for datagrid by inherting wpf toolkit datagrid. i want the style to be added in code behind. Any idea to implement the same would be appreciated.

Thanks in advance
Kartheesh

sousoux Jun 19, 2010 at 2:01 PM 
Since this took me a while to find if you want a ComboBox to drop down straight away hook up its loaded event and:

private void ComboBox_Loaded(object sender, RoutedEventArgs e)
{
((ComboBox)sender).IsDropDownOpen = true;
}

kainhart Jun 3, 2010 at 11:51 PM 
I placed the style shown above in a new Style that I've defined in a resource dictionary but when I try to build I get the following error.

The event 'PreviewMouseLeftButtonDown' cannot be specified on a Target tag in a Style. Use an EventSetter instead.

Is this possible? I'm attempting to wrap the DataGrid up with a control that inherits from the WpfToolkit DataGrid so that I can add the functionality described here to a single control that I can reuse throughout different portions of my app.

gshaffer Mar 18, 2010 at 8:18 PM 
The above code works great for me. I do have a question though. After the first click into a cell, is there a way to programmatically force input into the provided editor? For instance, if I have a combobox, I'd like for the combobox to be expanded when the user performs the first click. This would eliminate yet another click, which is important to my endusers.

sukumarthota Feb 24, 2010 at 1:09 AM 
I got rid of above error by including style tag inside datagrid resources. Now I wanted to know how to save the edited value to database?

sukumarthota Feb 24, 2010 at 1:04 AM 
I am getting this error when using singleclick code given above:
"itemcollection must be empty before using Itemsource". Can someone help here. Thanks.

htuomola Aug 7, 2009 at 12:23 PM 
Hi, using this method alone seems to leave all the rows/cells selected.
Adding "dataGrid.SelectedItems.Clear();" after "if (dataGrid != null)" fixed the problem.

Borvik Feb 16, 2009 at 4:30 PM 
I managed to find a way that suited my needs (reverse tabbing still doesn't work).

Here is one of my columns (I decided NO to textblocks - and have a single cell template):
<my:DataGridTemplateColumn Header="Item #">
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=ItemNumber}" />
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
I also have similar column for a CheckBox (I didn't like the built in column).

The changes a similar to the SingleClick:

<Style TargetType="{x:Type my:DataGridCell}">
<EventSetter Event="GotFocus" Handler="DataGridCell_GotFocus"></EventSetter>
</Style>


Private Sub DataGridCell_GotFocus(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)
Dim cell As DataGridCell = CType(sender, DataGridCell)
Dim childTxt As TextBox = FindVisualChild(Of TextBox)(cell)
If childTxt IsNot Nothing Then
If Not childTxt.IsFocused Then
Keyboard.Focus(childTxt)
End If
Exit Sub
End If

Dim childChk As CheckBox = FindVisualChild(Of CheckBox)(cell)
If childChk IsNot Nothing Then
If Not childChk.IsFocused Then
Keyboard.Focus(childChk)
End If
Exit Sub
End If
End Sub

Private Shared Function FindVisualChild(Of T As UIElement)(ByVal element As UIElement) As T
Dim child As UIElement = element
While child IsNot Nothing
Dim correctlyTyped As T = TryCast(child, T)
If correctlyTyped IsNot Nothing Then Return correctlyTyped
If VisualTreeHelper.GetChildrenCount(child) < 1 Then Exit While
child = CType(VisualTreeHelper.GetChild(child, 0), UIElement)
End While
Return Nothing
End Function

You would have to modify the GotFocus event handler to suit your individual needs.

NetContractor Nov 16, 2008 at 12:16 AM 
Is there an easy way to fix the tabbing through the grid? If I have template columns I seem to need to tab twice before getting the focus?