PowerShell DataGridView根据单元格值禁止选中指定行方法
DataGridView指定行禁止选中实现方案
DataGridView 原生未提供行级的禁选属性:
ReadOnly属性仅控制单元格是否可编辑,不影响选中逻辑Locked、Enabled不是DataGridViewRow类的公开有效属性,直接调用会抛出异常
正确实现逻辑是通过选择状态变更事件拦截,只要检测到Number值为0的行被选中,立刻强制取消其选中状态,可覆盖手动点选、拖拽多选、键盘选择、全选等所有场景。
关键修改点
- 新增
RowStateChanged事件处理,自动拦截禁选行的选中操作 - 保留原有禁选行灰色背景的提示样式
- 原有全选复选框逻辑无需大幅修改,事件会自动过滤禁选行
- 修复原脚本中全局表数据重复累加的小问题
完整可运行代码
Function GenerateDataGrid { # 每次生成前清空全局表,避免数据重复累加 $Global:Table = @() For($Index = 1; $Index -le 30; $Index++) { $Record = [ordered]@{ Follow = $Index Number = Random(0..5) } $Global:Table += New-Object 'PSObject' -Property $Record } $dgvTest.DataSource = [System.Collections.ArrayList]$Global:Table # 初始化行样式:给Number=0的行设置灰色背景 ForEach ($Row in $dgvTest.Rows) { if($Row.Cells['Number'].Value -eq 0) { $Row.DefaultCellStyle.BackColor = [System.Drawing.Color]::FromArgb(255, 224, 224, 224) } } $dgvTest.ClearSelection() } Function ShowResults { $Rows = $dgvTest.SelectedRows Clear-Host ForEach ($Row in $Rows) { $Follow = $Row.Cells['Follow'].Value $Number = $Row.Cells['Number'].Value Write-Host "$Follow $Number" } } $Global:Table = @() Add-Type -AssemblyName System.Web Add-Type -AssemblyName System.Windows.Forms $frmDataGridTest = New-Object 'System.Windows.Forms.Form' $btnShow = New-Object 'System.Windows.Forms.Button' $chkAllItems = New-Object 'System.Windows.Forms.CheckBox' $btnCancel = New-Object 'System.Windows.Forms.Button' $dgvTest = New-Object 'System.Windows.Forms.DataGridView' # # frmDataGridTest # $frmDataGridTest.Controls.Add($btnShow) $frmDataGridTest.Controls.Add($chkAllItems) $frmDataGridTest.Controls.Add($btnCancel) $frmDataGridTest.Controls.Add($dgvTest) $frmDataGridTest.AutoScaleDimensions = New-Object System.Drawing.SizeF(6, 13) $frmDataGridTest.AutoScaleMode = 'Font' $frmDataGridTest.CancelButton = $btnCancel $frmDataGridTest.ClientSize = New-Object System.Drawing.Size(281, 464) $frmDataGridTest.Name = 'frmDataGridTest' $frmDataGridTest.StartPosition = 'CenterScreen' $frmDataGridTest.Text = 'Test DatagridView' # # btnShow # $btnShow.Location = New-Object System.Drawing.Point(106, 385) $btnShow.Name = 'btnShow' $btnShow.Size = New-Object System.Drawing.Size(75, 50) $btnShow.TabIndex = 3 $btnShow.Text = 'Show selected items' $btnShow.UseVisualStyleBackColor = $True # # chkAllItems # $chkAllItems.Location = New-Object System.Drawing.Point(22, 13) $chkAllItems.Name = 'chkAllItems' $chkAllItems.Size = New-Object System.Drawing.Size(240, 24) $chkAllItems.TabIndex = 2 $chkAllItems.Text = 'Select or unselect all items' $chkAllItems.UseVisualStyleBackColor = $True # # btnCancel # $btnCancel.DialogResult = 'Cancel' $btnCancel.Location = New-Object System.Drawing.Point(187, 385) $btnCancel.Name = 'btnCancel' $btnCancel.Size = New-Object System.Drawing.Size(75, 50) $btnCancel.TabIndex = 1 $btnCancel.Text = 'Cancel' $btnCancel.UseVisualStyleBackColor = $True # # dgvTest # $dgvTest.AllowUserToAddRows = $False $dgvTest.AllowUserToDeleteRows = $False $dgvTest.AllowUserToOrderColumns = $True $dgvTest.AllowUserToResizeRows = $False $dgvTest.AutoSizeColumnsMode = 'AllCells' $dgvTest.AutoSizeRowsMode = 'AllCells' $dgvTest.ClipboardCopyMode = 'Disable' $dgvTest.ColumnHeadersHeightSizeMode = 'AutoSize' $dgvTest.Location = New-Object System.Drawing.Point(22, 43) $dgvTest.Name = 'dgvTest' $dgvTest.ReadOnly = $True $dgvTest.Size = New-Object System.Drawing.Size(240, 315) $dgvTest.TabIndex = 0 $dgvTest.SelectionMode = 'FullRowSelect' # 核心:行状态变更事件,拦截禁选行的选中操作 $dgvTest.Add_RowStateChanged({ param($sender, $e) # 仅处理选中状态变化的行 if ($e.StateChanged -eq [System.Windows.Forms.DataGridViewElementStates]::Selected) { $targetRow = $e.Row # 跳过底部新增占位行 if ($targetRow.IsNewRow) { return } # 若为Number=0的禁选行,强制取消选中 if ($targetRow.Cells['Number'].Value -eq 0) { $targetRow.Selected = $false } } }) $frmDataGridTest.Add_Shown({GenerateDataGrid}) $chkAllItems.Add_CheckedChanged({ if($chkAllItems.Checked) { $dgvTest.SelectAll() } else { $dgvTest.ClearSelection() } }) $btnShow.Add_Click({ShowResults}) [void]$frmDataGridTest.ShowDialog() [void]$frmDataGridTest.Dispose()
效果说明
- 用户手动点击、拖拽多选、按键盘方向键选择时,Number值为0的灰色行始终无法被选中
- 点击全选复选框时,会自动跳过所有Number值为0的行,仅选中可选项
- 点击「Show selected items」输出结果时,不会包含任何禁选行数据
内容的提问来源于stack exchange,提问作者TheStingPilot
相关产品推荐
相关产品推荐

