如何处理DataGridView编辑控件的绘制问题?

6

我有一个 DataGridView,在每行的第一个单元格上绘制类似于TreeView的虚线。这是在RowPostPaint事件中完成的。当第一个单元格(即DataGridViewTextBoxCell)处于编辑模式时,这些线条将不会被绘制。如何处理编辑控件的绘制?标准的编辑控件没有Paint事件,如果可以避免,我不想创建新类型的单元格。


我刚遇到了和你完全一样的问题,尝试在选定的单元格中添加类似Excel的字形。当使用编辑控件时,绘制事件不会被调用。我目前正在研究使用PositionEditingPanel属性来缩小编辑控件,以便它不会干扰父单元格中的字形。如果我解决了这个问题,我会回复你的。 - Bryan
3个回答

3

首先将第一列单元格的左边距设置为16,这样在查看模式或编辑模式下,内容将使用给定的填充显示。

this.dataGridView1.Columns[0].DefaultCellStyle.Padding= new Padding(16,0,0,0);

然后处理CellPainting事件并执行以下步骤:

  1. 只画第一列,且RowIndex应该是>=0以避免渲染列标题
  2. 绘制你的树形线条或其他你想要的内容
  3. 取消默认绘制,使用e.Handled = true

下面是代码:

private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    //Only paint first column and RowIndex should be >=0 to avoid rendering column header
    if (e.ColumnIndex == 0 && e.RowIndex >= 0)
    {
        //Paint your tree lines or whatever you want
        using (var treePen = new Pen(Color.Gray, 1))
        {
            treePen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
            e.Paint(e.CellBounds, DataGridViewPaintParts.All);
            e.Graphics.DrawLine(treePen,
                new Point(e.CellBounds.Left + 4, e.CellBounds.Top),
                new Point(e.CellBounds.Left + 4, e.CellBounds.Bottom));

            e.Graphics.DrawLine(treePen,
                new Point(e.CellBounds.Left + 4, e.CellBounds.Top + e.CellBounds.Height / 2),
                new Point(e.CellBounds.Left + 12, e.CellBounds.Top + e.CellBounds.Height / 2));
        }

        //Cancel default painting using e.Handled = true
        e.Handled = true;
    }
}

这里是屏幕截图:

输入图像描述


e.Handled 设置为 true 是危险的。设置 DataGridViewTextBoxCell 的值会覆盖它,调整大小不会重绘所有内容,留下一大堆混乱。更好的解决方案在这里:https://dev59.com/XGMm5IYBdhLWcg3wTtfi#35553181 - rémy
if (e.ColumnIndex == 0 && e.RowIndex >= 0) -> && - user5583316
@AlejandroAlis 在这种情况下,请随时在帖子中做出贡献并修复此类错别字。 - Reza Aghaei
抱歉,我不知道我可以这样做。我以为帖子只能由发布者编辑。 - user5583316

2

我曾通过创建自定义单元格类型并像Bryan所描述的那样缩小编辑控件来解决类似问题。这并不是特别困难,而且这是我知道的唯一防止编辑控件在所有内容上绘制的方法。

以下类似的代码可能适用于您:

public class PaintAccommodatingTextBoxCell : DataGridViewTextBoxCell
{
    // Adjust the editing panel, so that custom painting isn't
    // drawn over when cells go into edit mode.
    public override Rectangle PositionEditingPanel(Rectangle cellBounds, Rectangle cellClip, DataGridViewCellStyle cellStyle, bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded, bool isFirstDisplayedColumn, bool isFirstDisplayedRow)
    {
        // First, let base class do its adjustments
        Rectangle controlBounds = base.PositionEditingPanel(cellBounds, cellClip, cellStyle, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedColumn, isFirstDisplayedRow);

        // Shrink the bounds here...

        return controlBounds;
    }
}

public class PaintAccommodatingTextBoxColumn : DataGridViewTextBoxColumn
{
    PaintAccommodatingTextBoxCell templateCell;

    public PaintAccommodatingTextBoxColumn()
    {
        templateCell = new PaintAccommodatingTextBoxCell();
    }

    public override DataGridViewCell CellTemplate
    {
        get
        {
            return templateCell;
        }
        set
        {
            PaintAccommodatingTextBoxCell newTemplate = value as PaintAccommodatingTextBoxCell;
            if (newTemplate == null)
                throw new ArgumentException("Template must be a PaintAccommodatingTextBoxCell");
            else
                templateCell = newTemplate;
        }
    }
}

在处理同一个问题时,我发现在调用base.PositionEditingPanel之前需要修改cellBounds参数,而不是简单地修改返回值。否则,编辑控件将被调整大小,但是编辑面板将遮挡自定义单元格绘制。 - asponge

0
尝试处理DataGridView.CellPainting事件。

没有成功 - 它被调用了,但是当单元格处于编辑模式时,它不会绘制任何可见的内容。 - Simon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接