I came up with the code below, but there has to be a better way.
I don't think there is a better way, all what you can find around are just variations of your code snippet, either by using simple nested loops as you do, or by looping the results returned by LINQ quires.
However, you can optimize the code taking into account the DataGridView.SelectionMode property. You don't need nested or complete loops when it is set to FullColumnSelect or FullRowSelect values. Moreover, for the other selection mode values, you can optionally make a connected selection, that is, selecting all the cells between the given staring and ending cells of the given rows.
Here's an extension method example, add a new module if you don't have one or to separate the project's extension methods. Switch to the Solution Explorer window, select the project, right mouse click, go to Add - Module, name it Extensions for example and hit Add.
Imports System.Runtime.CompilerServices
Module Extensions
<Extension>
Public Sub SelectRange(
gridCntl As DataGridView,
rowStart As Integer,
colStart As Integer,
rowEnd As Integer,
colEnd As Integer,
connected As Boolean)
gridCntl.ClearSelection()
Select Case gridCntl.SelectionMode
Case DataGridViewSelectionMode.FullRowSelect
' Just Select the rows...
For row = rowStart To rowEnd
gridCntl.Rows(row).Selected = True
Next
Case DataGridViewSelectionMode.FullColumnSelect
' Just select the columns of the first row...
For row = rowStart To rowStart
For col = colStart To colEnd
gridCntl(col, row).Selected = True
Next
Next
Case Else
' For the rest, select either normal or connected selection...
Dim colFrom As Integer = colStart, colTo As Integer
For row = rowStart To rowEnd
Dim notLastRow As Boolean = row < rowEnd
colTo = If(connected AndAlso notLastRow,
gridCntl.Columns.Count - 1,
colEnd)
For col = colFrom To colTo
gridCntl(col, row).Selected = True
Next
colFrom = If(connected AndAlso notLastRow, 0, colStart)
Next
End Select
End Sub
End Module
Call the extension method...
Sub SomeCaller()
SomeDGV.SelectRange(1, 2, 5, 1, True) ' or False...
End Sub
Side Notes
- No point from passing a reference type or a control
ByRef.
- The
DataGridView indexer receives the column and row indices respectively.