编辑时如何在 DataGridView 单元格周围绘制边框? [英] How do you draw a border around a DataGridView cell while it's being edited?

查看:21
本文介绍了编辑时如何在 DataGridView 单元格周围绘制边框?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在编辑时在 DataGridView 单元格周围绘制红色边框.

我设法在选定的单元格周围绘制了一个红色边框,而未使用此代码对其进行

private void Form1_Load(object sender, EventArgs e){this.Width = 650;this.Height = 250;dataGridView1.Left = 5;dataGridView1.Top = 5;dataGridView1.Width = 600;dataGridView1.Height = 175;DataTable dt = new DataTable("测试表");dt.Columns.Add("第一列");dt.Columns.Add("第二列");dt.Columns.Add("第三列");dt.Columns.Add("第 4 列");dt.Columns.Add("第 5 列");dt.Rows.Add(dt.NewRow());dt.Rows.Add(dt.NewRow());dt.Rows.Add(dt.NewRow());dt.Rows.Add(dt.NewRow());dt.Rows.Add(dt.NewRow());dataGridView1.DataSource = dt;dataGridView1.AllowUserToAddRows = false;dataGridView1.AllowUserToDeleteRows = false;dataGridView1.MultiSelect = false;dataGridView1.SelectionMode = DataGridViewSelectionMode.CellSelect;dataGridView1.DefaultCellStyle.SelectionBackColor = Color.White;dataGridView1.CellPainting += new System.Windows.Forms.DataGridViewCellPaintingEventHandler(this.dataGridView1_CellPainting);dataGridView1.EditingControlShowing += new System.Windows.Forms.DataGridViewEditingControlShowingEventHandler(this.dataGridView1_EditingControlShowing);}私有无效 dataGridView1_CellPainting(对象发送者,DataGridViewCellPaintingEventArgs e){if (e.ColumnIndex != -1 && e.RowIndex != -1 && dataGridView1[e.ColumnIndex, e.RowIndex].Selected){使用 (Brush borderBrush = new SolidBrush(Color.Red)){使用 (Pen borderPen = new Pen(borderBrush, 2)){矩形 rectDimensions = e.CellBounds;rectDimensions.Width -= 2;rectDimensions.Height -= 2;rectDimensions.X = rectDimensions.Left + 1;rectDimensions.Y = rectDimensions.Top + 1;e.Graphics.DrawRectangle(borderPen, rectDimensions);e.handled = true;}}}}

产生这个结果:

但是,当您编辑单元格时会发生这种情况:

似乎 EditingControl 将自己绘制在我大部分红色边框的顶部.不幸的是,我找不到解决此问题的方法,因此我的红色边框将始终完全显示.

我该怎么做???

<小时>


这是我迄今为止尝试过的:

1. 处理 EditingControlShowing() 事件以手动重新绘制边框是这样的:

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e){图形 gfx = e.Control.CreateGraphics();使用 (Brush borderBrush = new SolidBrush(Color.Red)){使用 (Pen borderPen = new Pen(borderBrush, 2)){矩形 rectDimensions = e.Control.ClientRectangle;rectDimensions.Width -= 2;rectDimensions.Height -= 2;rectDimensions.X = rectDimensions.Left + 1;rectDimensions.Y = rectDimensions.Top + 1;gfx.DrawRectangle(borderPen, rectDimensions);}}}

但这并没有画出任何东西.我尝试了一些变体,但所有这些变体仍然没有在这里绘制.


2. 然后我尝试处理 EditingControlPaint() 事件像这样:

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e){e.Control.Paint -= new PaintEventHandler(dataGridView1_EditingControl_Paint);e.Control.Paint += new PaintEventHandler(dataGridView1_EditingControl_Paint);}void dataGridView1_EditingControl_Paint(对象发送者,PaintEventArgs e){MessageBox.Show("正在启动 EditingControl Paint() 事件...");}

但是这个事件甚至没有触发.后来我在某处读到EditingControl 使用普通的 TextBox,它不会触发Paint() 事件,因为它由 Windows 处理.


3. 最后,我没有尝试重新绘制另一个边框,而是决定尝试通过调整 EditingControl 的大小来解决它比我的边界小,希望边界会显示出来它,像这样:

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e){e.Control.Resize -= new EventHandler(dataGridView1_EditingControl_Resize);e.Control.Resize += new EventHandler(dataGridView1_EditingControl_Resize);}void dataGridView1_EditingControl_Resize(object sender, EventArgs e){dataGridView1.EditingControl.Left = 20;}

然而,这只是给了我这个结果:

所以 TextBox 确实移到了左边,但似乎还有另一个它下面的控件仍然挡住了我的红色边框.但是,无论如何我都找不到访问权限到那个控件来调整它的大小,所以这对我也不起作用.


4. 我还尝试使用上面 #1 中的代码在 Resize() 事件中重新绘制边框,但仍然没有任何效果.虽然,使用 dataGridView1.EditingControl.BackColor = Color.Red; 确实有效,所以我可以在这里格式化控件的某些部分,但似乎试图绘制边框不是其中之一.>

我想要做的就是在编辑单元格时在单元格周围显示一个红色边框.你知道我该怎么做吗?

解决方案

可以使用一些设置和绘制单元格的特定部分来完成.如此:

首先设置

这是编辑单元格时的结果截图

这里是单元格绘制事件的代码:

private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e){//只绘制网格内容单元格而不是ColumnHeader单元格和RowHeader单元格if (e.ColumnIndex > -1 & e.RowIndex > -1){//左边框和上边框的钢笔使用 (var backGroundPen = new Pen(e.CellStyle.BackColor, 1))//下边框和右边框的钢笔使用 (var gridlinePen = new Pen(dataGridView1.GridColor, 1))//用于选定单元格边框的钢笔使用 (var selectedPen = new Pen(Color.Red, 1)){var topLeftPoint = new Point(e.CellBounds.Left, e.CellBounds.Top);var topRightPoint = new Point(e.CellBounds.Right - 1, e.CellBounds.Top);var bottomRightPoint = new Point(e.CellBounds.Right - 1, e.CellBounds.Bottom - 1);var bottomleftPoint = new Point(e.CellBounds.Left, e.CellBounds.Bottom - 1);//在这里绘制选中的单元格if (this.dataGridView1[e.ColumnIndex, e.RowIndex].Selected){//绘制除边框外的所有部分.e.Paint(e.ClipBounds, DataGridViewPaintParts.All & ~DataGridViewPaintParts.Border);//在此处绘制选中的单元格边框e.Graphics.DrawRectangle(selectedPen, new Rectangle(e.CellBounds.Left, e.CellBounds.Top, e.CellBounds.Width - 1, e.CellBounds.Height - 1));//处理此单元格的绘制,停止默认渲染.e.handled = true;}//在此处绘制未选中的单元格别的{//绘制除边框外的所有部分.e.Paint(e.ClipBounds, DataGridViewPaintParts.All & ~DataGridViewPaintParts.Border);//第一行单元格的上边框应该是背景色如果(e.RowIndex == 0)e.Graphics.DrawLine(backGroundPen, topLeftPoint, topRightPoint);//第一列单元格的左边框应该是背景色如果(e.ColumnIndex == 0)e.Graphics.DrawLine(backGroundPen, topLeftPoint, bottomleftPoint);//最后一行单元格的底部边框应为gridLine颜色if (e.RowIndex == dataGridView1.RowCount - 1)e.Graphics.DrawLine(gridlinePen,bottomRightPoint,bottomleftPoint);else//非最后一行单元格的下边框应为背景色e.Graphics.DrawLine(backGroundPen,bottomRightPoint,bottomleftPoint);//最后一列单元格的右边框应为gridLine颜色如果(e.ColumnIndex == dataGridView1.ColumnCount - 1)e.Graphics.DrawLine(gridlinePen,bottomRightPoint,topRightPoint);else//非最后一列单元格的右边框应为背景色e.Graphics.DrawLine(backGroundPen,bottomRightPoint,topRightPoint);//非第一行单元格的上边框应该是gridLine颜色,并且应该在右边框之后绘制在这里如果(e.RowIndex > 0)e.Graphics.DrawLine(gridlinePen, topLeftPoint, topRightPoint);//非第一列单元格的左边框应该是gridLine颜色,并且它们应该在底边框之后绘制在这里如果(e.ColumnIndex > 0)e.Graphics.DrawLine(gridlinePen, topLeftPoint, bottomleftPoint);//我们处理了这个单元格的绘制,停止默认渲染.e.handled = true;}}}}

I would like to draw a red border around a DataGridView cell while it's being edited.

I've managed to draw a red border around the selected cell while it's not being edited using this code:

private void Form1_Load(object sender, EventArgs e)
{
    this.Width = 650;
    this.Height = 250;
    dataGridView1.Left = 5;
    dataGridView1.Top = 5;
    dataGridView1.Width = 600;
    dataGridView1.Height = 175;

    DataTable dt = new DataTable("Test Table");
    dt.Columns.Add("Column 1");
    dt.Columns.Add("Column 2");
    dt.Columns.Add("Column 3");
    dt.Columns.Add("Column 4");
    dt.Columns.Add("Column 5");
    dt.Rows.Add(dt.NewRow());
    dt.Rows.Add(dt.NewRow());
    dt.Rows.Add(dt.NewRow());
    dt.Rows.Add(dt.NewRow());
    dt.Rows.Add(dt.NewRow());
    dataGridView1.DataSource = dt;

    dataGridView1.AllowUserToAddRows = false;
    dataGridView1.AllowUserToDeleteRows = false;
    dataGridView1.MultiSelect = false;
    dataGridView1.SelectionMode = DataGridViewSelectionMode.CellSelect;
    dataGridView1.DefaultCellStyle.SelectionBackColor = Color.White;
    dataGridView1.CellPainting += new System.Windows.Forms.DataGridViewCellPaintingEventHandler(this.dataGridView1_CellPainting);
    dataGridView1.EditingControlShowing += new System.Windows.Forms.DataGridViewEditingControlShowingEventHandler(this.dataGridView1_EditingControlShowing);
}

private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    if (e.ColumnIndex != -1 && e.RowIndex != -1 && dataGridView1[e.ColumnIndex, e.RowIndex].Selected)
    {
        using (Brush borderBrush = new SolidBrush(Color.Red))
        {
            using (Pen borderPen = new Pen(borderBrush, 2))
            {
                Rectangle rectDimensions = e.CellBounds;
                rectDimensions.Width -= 2;
                rectDimensions.Height -= 2;
                rectDimensions.X = rectDimensions.Left + 1;
                rectDimensions.Y = rectDimensions.Top + 1;

                e.Graphics.DrawRectangle(borderPen, rectDimensions);

                e.Handled = true;
            }
        }
    }
}

Which produces this result:

However, when you edit a cell this happens:

It seems the EditingControl is drawing itself over the top of most of my red border. Unfortunately, I can't find a way to fix this so my red border will stay fully displayed at all times.

How can I do this???



Here's what I've tried so far:

1. Handling the EditingControlShowing() event to manually re-draw the border like this:

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    Graphics gfx = e.Control.CreateGraphics();

    using (Brush borderBrush = new SolidBrush(Color.Red))
    {
        using (Pen borderPen = new Pen(borderBrush, 2))
        {
            Rectangle rectDimensions = e.Control.ClientRectangle;
            rectDimensions.Width -= 2;
            rectDimensions.Height -= 2;
            rectDimensions.X = rectDimensions.Left + 1;
            rectDimensions.Y = rectDimensions.Top + 1;

            gfx.DrawRectangle(borderPen, rectDimensions);
        }
    }
}

But this didn't draw anything. I tried a few variations of this but all of them still drew nothing here.


2. I then tried to handle the Paint() event of the EditingControl like this:

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    e.Control.Paint -= new PaintEventHandler(dataGridView1_EditingControl_Paint);
    e.Control.Paint += new PaintEventHandler(dataGridView1_EditingControl_Paint);
}

void dataGridView1_EditingControl_Paint(object sender, PaintEventArgs e)
{
    MessageBox.Show("Starting EditingControl Paint() Event...");
}

But this event doesn't even fire. I later read somewhere that the EditingControl uses a normal TextBox, which doesn't fire the Paint() event because it's handled by Windows instead.


3. Finally, rather than trying to re-paint another border, I decided to try and hack around it by resizing the EditingControl to be smaller than my border in hopes the border would then show around it, like this:

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    e.Control.Resize -= new EventHandler(dataGridView1_EditingControl_Resize);
    e.Control.Resize += new EventHandler(dataGridView1_EditingControl_Resize);
}

void dataGridView1_EditingControl_Resize(object sender, EventArgs e)
{
    dataGridView1.EditingControl.Left = 20;
}

However, that just gave me this result:

So the TextBox did move over to the Left, but it seems there is another control underneath it that is still blocking my red border. However, I can't find anyway to get access to that control to resize it so this didn't work for me either.


4. I also tried using the code from #1 above to re-draw the border in the Resize() event, but that still did nothing. Although, using dataGridView1.EditingControl.BackColor = Color.Red; did work so I can format some parts of the control here, but it seems trying to draw a border isn't one of them.

All I want to do is keep a red border showing around the cell while it's being edited. Do you know how I can do this?

解决方案

It can be done using some settings and painting specific parts of cell. To so so:

First, set CellBorderStyle to Raised or Sunken in designer or simply in form load code:

this.dataGridView1.CellBorderStyle = DataGridViewCellBorderStyle.Raised;

Then draw cells using these specific ordered rules:

  1. Draw only grid content cells not ColumnHeader cells nor RowHeader
  2. When drawing selected cells, first paint all parts except borders using e.Paint(...); then draw borders yourself
  3. Set e.Handled=true to prevent default painting
  4. When drawing non-selected cells, first paint all parts except borders using e.Paint(...)
  5. Draw top border of cells of first row and left border of cells of first column using grid background color
  6. Draw bottom border of cells of last row and right border of cells of last column using grid line color
  7. Draw bottom border of cells of non-last row and right border of cells of non-last column using grid background color
  8. Draw top border cells of non-first row and left border of cells of non-last column using grid line color 9.Set e.Handled=true to prevent default painting

This is screenshot of result, after select

and here is screenshot of result, when editing cell

and here is the code of cell paint event:

private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    //Draw only grid content cells not ColumnHeader cells nor RowHeader cells
    if (e.ColumnIndex > -1 & e.RowIndex > -1)
    {
        //Pen for left and top borders
        using (var backGroundPen = new Pen(e.CellStyle.BackColor, 1))
        //Pen for bottom and right borders
        using (var gridlinePen = new Pen(dataGridView1.GridColor, 1))
        //Pen for selected cell borders
        using (var selectedPen = new Pen(Color.Red, 1))
        {
            var topLeftPoint = new Point(e.CellBounds.Left, e.CellBounds.Top);
            var topRightPoint = new Point(e.CellBounds.Right - 1, e.CellBounds.Top);
            var bottomRightPoint = new Point(e.CellBounds.Right - 1, e.CellBounds.Bottom - 1);
            var bottomleftPoint = new Point(e.CellBounds.Left, e.CellBounds.Bottom - 1);

            //Draw selected cells here
            if (this.dataGridView1[e.ColumnIndex, e.RowIndex].Selected)
            {
                //Paint all parts except borders.
                e.Paint(e.ClipBounds, DataGridViewPaintParts.All & ~DataGridViewPaintParts.Border);

                //Draw selected cells border here
                e.Graphics.DrawRectangle(selectedPen, new Rectangle(e.CellBounds.Left, e.CellBounds.Top, e.CellBounds.Width - 1, e.CellBounds.Height - 1));

                //Handled painting for this cell, Stop default rendering.
                e.Handled = true;
            }
            //Draw non-selected cells here
            else
            {
                //Paint all parts except borders.
                e.Paint(e.ClipBounds, DataGridViewPaintParts.All & ~DataGridViewPaintParts.Border);

                //Top border of first row cells should be in background color
                if (e.RowIndex == 0)
                    e.Graphics.DrawLine(backGroundPen, topLeftPoint, topRightPoint);

                //Left border of first column cells should be in background color
                if (e.ColumnIndex == 0)
                    e.Graphics.DrawLine(backGroundPen, topLeftPoint, bottomleftPoint);

                //Bottom border of last row cells should be in gridLine color
                if (e.RowIndex == dataGridView1.RowCount - 1)
                    e.Graphics.DrawLine(gridlinePen, bottomRightPoint, bottomleftPoint);
                else  //Bottom border of non-last row cells should be in background color
                    e.Graphics.DrawLine(backGroundPen, bottomRightPoint, bottomleftPoint);

                //Right border of last column cells should be in gridLine color
                if (e.ColumnIndex == dataGridView1.ColumnCount - 1)
                    e.Graphics.DrawLine(gridlinePen, bottomRightPoint, topRightPoint);
                else //Right border of non-last column cells should be in background color
                    e.Graphics.DrawLine(backGroundPen, bottomRightPoint, topRightPoint);

                //Top border of non-first row cells should be in gridLine color, and they should be drawn here after right border
                if (e.RowIndex > 0)
                    e.Graphics.DrawLine(gridlinePen, topLeftPoint, topRightPoint);

                //Left border of non-first column cells should be in gridLine color, and they should be drawn here after bottom border
                if (e.ColumnIndex > 0)
                    e.Graphics.DrawLine(gridlinePen, topLeftPoint, bottomleftPoint);

                //We handled painting for this cell, Stop default rendering.
                e.Handled = true;
            }
        }
    }
}

这篇关于编辑时如何在 DataGridView 单元格周围绘制边框?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆