Windows Forms DataGridView如何实现自适应换行+超量截断显示省略号?
解决Windows Forms DataGridView长文本「换行+行高上限后省略」的需求
这个需求确实有点 tricky,因为DataGridView默认的CellStyle组合没办法直接实现「换行显示+行高到上限后省略」的效果——要么全换行显示要么单行截断。不过我们可以通过自定义单元格绘制的方式来搞定,而且完全不会影响原始内容的复制,刚好符合你的要求。
核心思路
- 保留单元格原始值不修改,确保复制时能拿到完整文本;
- 手动控制行高:自动计算内容所需行高,但不超过设定的最大值;
- 通过
CellPainting事件自定义绘制逻辑:当内容超出最大行高时,绘制带省略号的换行文本,否则正常显示换行内容。
完整PowerShell代码实现
# 创建基础DataGridView控件 $TestGridView = New-Object System.Windows.Forms.DataGridView -Property @{ Name="TestDataGridView" AllowUserToAddRows = $False AllowUserToDeleteRows = $False Location = "14,225" Size = "1041,328" TabIndex = 1 DefaultCellStyle= @{ WrapMode = [System.Windows.Forms.DataGridViewTriState]::True Padding = New-Object System.Windows.Forms.Padding(2) Font = New-Object System.Drawing.Font("Segoe UI", 9) # 可根据需求调整字体 } RowHeadersVisible=$False AutoSizeColumnsMode='Fill' AutoSizeRowsMode = [System.Windows.Forms.DataGridViewAutoSizeRowsMode]::None # 手动控制行高 Anchor = 'Left, Right, Top, Bottom' } # 设定最大允许的行高(比如最多显示3行文本) $maxLineCount = 3 $font = $TestGridView.DefaultCellStyle.Font $singleLineHeight = [System.Windows.Forms.TextRenderer]::MeasureText("A", $font).Height + $TestGridView.DefaultCellStyle.Padding.Vertical $maxRowHeight = $singleLineHeight * $maxLineCount # 绑定CellFormatting事件:自动计算并设置行高(不超过最大值) $TestGridView.add_CellFormatting({ param($sender, $e) if ($e.RowIndex < 0 -or $e.Value -eq $null) { return } $cellText = $e.Value.ToString() # 计算单元格可用宽度(减去padding) $cellWidth = $sender.Columns[$e.ColumnIndex].Width - $sender.DefaultCellStyle.Padding.Horizontal # 计算文本在当前宽度下需要的高度(允许换行) $textSize = [System.Windows.Forms.TextRenderer]::MeasureText( $cellText, $sender.DefaultCellStyle.Font, New-Object System.Drawing.Size($cellWidth, [int]::MaxValue), [System.Windows.Forms.TextFormatFlags]::WordBreak ) # 确定最终行高:取需求高度和最大行高中的较小值 $neededHeight = $textSize.Height + $sender.DefaultCellStyle.Padding.Vertical $finalHeight = [Math]::Min($neededHeight, $maxRowHeight) # 避免重复设置行高 if ($sender.Rows[$e.RowIndex].Height -ne $finalHeight) { $sender.Rows[$e.RowIndex].Height = $finalHeight } }) # 绑定CellPainting事件:自定义绘制文本(超出时显示省略号) $TestGridView.add_CellPainting({ param($sender, $e) # 跳过表头和空单元格 if ($e.RowIndex < 0 -or $e.ColumnIndex < 0 -or $e.Value -eq $null) { return } $cellText = $e.Value.ToString() # 计算单元格的可用绘制区域(减去padding) $drawRect = New-Object System.Drawing.Rectangle( $e.CellBounds.X + $e.CellStyle.Padding.Left, $e.CellBounds.Y + $e.CellStyle.Padding.Top, $e.CellBounds.Width - $e.CellStyle.Padding.Horizontal, $e.CellBounds.Height - $e.CellStyle.Padding.Vertical ) # 先绘制默认的单元格背景和边框,保持原有样式 $e.PaintBackground($e.ClipBounds, $true) $e.PaintBorder($e.ClipBounds, $e.CellStyle, $true, $true, $true, $true) # 计算文本在当前绘制区域内的显示状态 $textSize = [System.Windows.Forms.TextRenderer]::MeasureText( $cellText, $e.CellStyle.Font, New-Object System.Drawing.Size($drawRect.Width, [int]::MaxValue), [System.Windows.Forms.TextFormatFlags]::WordBreak ) if ($textSize.Height > $drawRect.Height) { # 内容超出最大行高,绘制带省略号的换行文本 [System.Windows.Forms.TextRenderer]::DrawText( $e.Graphics, $cellText, $e.CellStyle.Font, $drawRect, $e.CellStyle.ForeColor, $e.CellStyle.BackColor, [System.Windows.Forms.TextFormatFlags]::WordBreak -bor [System.Windows.Forms.TextFormatFlags]::EndEllipsis ) } else { # 内容未超出,正常绘制换行文本 [System.Windows.Forms.TextRenderer]::DrawText( $e.Graphics, $cellText, $e.CellStyle.Font, $drawRect, $e.CellStyle.ForeColor, $e.CellStyle.BackColor, [System.Windows.Forms.TextFormatFlags]::WordBreak ) } # 取消默认绘制逻辑,避免重复渲染 $e.Handled = $true }) # 示例:添加测试数据 $table = New-Object System.Data.DataTable $table.Columns.Add("测试文本列") $table.Rows.Add("这是一段短文本,会正常换行显示") $table.Rows.Add("这是一段非常长的测试文本,用来验证行高上限后的省略效果。这里会填充很多内容,确保文本的高度超过我们设定的最大行高,这样就能看到末尾的省略号了。同时复制这个单元格的内容时,你会拿到完整的文本,不会丢失任何部分。") $TestGridView.DataSource = $table # 显示窗体(示例用) $form = New-Object System.Windows.Forms.Form -Property @{Size="1080,600"; Text="DataGridView文本换行+省略测试"} $form.Controls.Add($TestGridView) $form.ShowDialog() | Out-Null
关键细节说明
- 行高控制:通过
CellFormatting事件计算每行所需高度,限制在$maxRowHeight以内,确保行高不会无限扩展; - 自定义绘制:
CellPainting事件中,我们先保留默认的背景和边框样式,再根据内容高度决定是否绘制省略号,完全不修改单元格的原始Value; - 灵活性:你可以通过调整
$maxLineCount来控制最多显示的行数,也可以针对不同列设置不同的最大行高(在事件中通过$e.ColumnIndex判断即可)。
内容的提问来源于stack exchange,提问作者Aldo
相关产品推荐
相关产品推荐

