I want to select a range (or rectangle) of cells in a .Net DataGridView. I could not find a built in method to do this. I came up with the code below, but there has to be a better way.
Public Sub setDataGridViewSelectedRange(ByRef gridCntl As DataGridView, rowStart As Int32, colStart As Int32, rowEnd As Int32, colEnd As Int32)
Dim curRow As Int32
Dim curCol As Int32
For curRow = rowStart To rowEnd
For curCol = colStart To colEnd
gridCntl(curRow, curCol).Selected = True
Next
Next
End Sub
CodePudding user response:
Are you using System.Windows.Forms? In WPF the DataGrid control has two properties SelectionMode and SelectionUnit.
The SelectionMode can be set to Single or Extended to define if one or multiple units can be selected simultaneously. The SelectionUnit defines the scope of one selection unit. It can be set to Cell, CellAndRowHeader and FullRow. https://www.wpftutorial.net/datagrid.html
CodePudding user response:
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.