67

I'd like to deselect all selected rows in a DataGridView control when the user clicks on a blank (non-row) part of the control.
How can I do this?

Shin
  • 664
  • 2
  • 13
  • 30
tinmac
  • 2,357
  • 3
  • 25
  • 41

6 Answers6

144

To deselect all rows and cells in a DataGridView, you can use the ClearSelection method:

myDataGridView.ClearSelection()

If you don't want even the first row/cell to appear selected, you can set the CurrentCell property to Nothing/null, which will temporarily hide the focus rectangle until the control receives focus again:

myDataGridView.CurrentCell = Nothing

To determine when the user has clicked on a blank part of the DataGridView, you're going to have to handle its MouseUp event. In that event, you can HitTest the click location and watch for this to indicate HitTestInfo.Nowhere. For example:

Private Sub myDataGridView_MouseUp(ByVal sender as Object, ByVal e as System.Windows.Forms.MouseEventArgs)
    ''# See if the left mouse button was clicked
    If e.Button = MouseButtons.Left Then
        ''# Check the HitTest information for this click location
        If myDataGridView.HitTest(e.X, e.Y) = DataGridView.HitTestInfo.Nowhere Then
            myDataGridView.ClearSelection()
            myDataGridView.CurrentCell = Nothing
        End If
    End If
End Sub

Of course, you could also subclass the existing DataGridView control to combine all of this functionality into a single custom control. You'll need to override its OnMouseUp method similar to the way shown above. I also like to provide a public DeselectAll method for convenience that both calls the ClearSelection method and sets the CurrentCell property to Nothing.

(Code samples are all arbitrarily in VB.NET because the question doesn't specify a language—apologies if this is not your native dialect.)

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • This didn't seem to work for me, I got it working but my datagridview didn't have a `=HitTestInfo.Nowhere` i had to change it to..... `If myDataGridView.HitTest(e.X, e.Y) Is myDataGridView.HitTest(e.X, e.Y) Then`... works as intended, but not 100% sure why it works. First HitTest code implemented. – nora Jun 06 '16 at 10:03
  • 1
    @nora The code you wrote doesn't really make any sense. It should not have worked. The [`Is` operator](https://msdn.microsoft.com/en-us/library/kb136x1y.aspx) compares the types of two reference variables. So all you're doing there is checking that the `HitTest` property returns a value of the same type as the...`HitTest` property. It's like saying `If True = True`. – Cody Gray - on strike Jun 07 '16 at 09:53
  • @nora (continued) In reality, the [`HitTest` property](https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.hittest.aspx) returns a value of type `HitTestInfo`. [`HitTestInfo`](https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.hittestinfo.aspx) is a non-inheritable class that contains, among other things, a static field named `Nowhere`. This is the field that you need to compare against. I suppose what's tripping you up is that the `HitTestInfo` class is a *nested* class of `DataGridView`. I've updated my answer to explicitly qualify it. – Cody Gray - on strike Jun 07 '16 at 09:54
  • I was thinking about this before, are there not perhaps two 'HitTests', one for the Blank Space, and One for the Cells occupied space?.. So the HitTest above is saying `If Blank Space Is Blank Space Then`.. Where the cell version would be something like `If Cell Space Is Cell Space Then`.. maybe?.. just wondering why mine works with a `True = True` situation ? If I click a Cell the highlight stays, if i click a blank space it goes away. – nora Jun 07 '16 at 14:47
  • Do not call ClearSelection too soon! – TaW Jun 30 '16 at 16:39
  • 2
    @TaW That comment would be more helpful if you specified what you meant by "too soon". – Cody Gray - on strike Jul 01 '16 at 07:17
  • 3
    Well, I found that e.g. after filling a DGV in the constructor __is__ 'too soon'. Moving the ClearSelection to Form_Shown works fine.. Not sure what the exact rule is; maybe something like 'after layout'? I added the note as there are many comments on similar post that find ClearSelection doesn't work for them. So adding it to theis high-voted answer seemd like a good idea. – TaW Jul 01 '16 at 07:28
  • Sorry to revisit an old thread but I ran into the same problems as @nora and, just for the benefit of future visitors, I think there's a syntactic issue with the code provided by Cody. You can't use `If myDataGridView.HitTest(e.X, e.Y) = DataGridView.HitTestInfo.Nowhere Then` because : Operator '=' is not defined for types 'DataGridView.HitTestInfo' - I believe this line should be written thus : `If myDataGridView.HitTest(e.X, e.Y).Type = DataGridViewHitTestType.None Then` (basically a VB version of tinmac's C# version below...) – Alan O'Brien Nov 16 '22 at 14:47
10

C# version:

if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            DataGridView.HitTestInfo hit = dgv_track.HitTest(e.X, e.Y);
            if (hit.Type == DataGridViewHitTestType.None)
            {
                dgv_track.ClearSelection();
                dgv_track.CurrentCell = null;
            }
        }
tinmac
  • 2,357
  • 3
  • 25
  • 41
3

i found out why my first row was default selected and found out how to not select it by default.

By default my datagridview was the object with the first tab-stop on my windows form. Making the tab stop first on another object (maybe disabling tabstop for the datagrid at all will work to) disabled selecting the first row

Mario
  • 582
  • 5
  • 18
  • This actually solved my problem too. For some strange reason changing the `TabStop` property to `false` seems to load the form without a selected `DataGridView` cell/index. – Apostrofix Jun 18 '14 at 07:10
  • This doesn't work. If you set a breakpoint on the SelectionChanged event and enable .NET Framework Source Stepping, you can see a call from OnHandleCreated() to MakeFirstDisplayedCellCurrentCell(). This is why it happens, not because it can be "tabbed" into. – computerGuyCJ Jul 24 '15 at 18:26
1

Set

dgv.CurrentCell = null;

when user clicks on a blank part of the dgv.

David
  • 5,356
  • 2
  • 26
  • 39
0

i have ran into the same problem and found a solution (not totally by myself, but there is the internet for)

Color blue  = ColorTranslator.FromHtml("#CCFFFF");
Color red = ColorTranslator.FromHtml("#FFCCFF");
Color letters = Color.Black;

foreach (DataGridViewRow r in datagridIncome.Rows)
{
    if (r.Cells[5].Value.ToString().Contains("1")) { 
        r.DefaultCellStyle.BackColor = blue;
        r.DefaultCellStyle.SelectionBackColor = blue;
        r.DefaultCellStyle.SelectionForeColor = letters;
    }
    else { 
        r.DefaultCellStyle.BackColor = red;
        r.DefaultCellStyle.SelectionBackColor = red;
        r.DefaultCellStyle.SelectionForeColor = letters;
    }
}

This is a small trick, the only way you can see a row is selected, is by the very first column (not column[0], but the one therefore). When you click another row, you will not see the blue selection anymore, only the arrow indicates which row have selected. As you understand, I use rowSelection in my gridview.

Mario
  • 582
  • 5
  • 18
0

In VB.net use for the Sub:

    Private Sub dgv_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles dgv.MouseUp
    ' deselezionare se click su vuoto
    If e.Button = MouseButtons.Left Then
        ' Check the HitTest information for this click location
        If Equals(dgv.HitTest(e.X, e.Y), DataGridView.HitTestInfo.Nowhere) Then
            dgv.ClearSelection()
            dgv.CurrentCell = Nothing
        End If
    End If
End Sub