You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows Forms DataGridView如何实现自适应换行+超量截断显示省略号?

解决Windows Forms DataGridView长文本「换行+行高上限后省略」的需求

这个需求确实有点 tricky,因为DataGridView默认的CellStyle组合没办法直接实现「换行显示+行高到上限后省略」的效果——要么全换行显示要么单行截断。不过我们可以通过自定义单元格绘制的方式来搞定,而且完全不会影响原始内容的复制,刚好符合你的要求。

核心思路

  1. 保留单元格原始值不修改,确保复制时能拿到完整文本;
  2. 手动控制行高:自动计算内容所需行高,但不超过设定的最大值;
  3. 通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:57:02