编辑时如何在 DataGridView 单元格周围绘制边框? [英] How do you draw a border around a DataGridView cell while it's being edited?
问题描述
我想在编辑时在 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. 然后我尝试处理 EditingControl
的 Paint()
事件像这样:
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:
- Draw only grid content cells not ColumnHeader cells nor RowHeader
- When drawing selected cells, first paint all parts except borders using e.Paint(...); then draw borders yourself
- Set e.Handled=true to prevent default painting
- When drawing non-selected cells, first paint all parts except borders using e.Paint(...)
- Draw top border of cells of first row and left border of cells of first column using grid background color
- Draw bottom border of cells of last row and right border of cells of last column using grid line color
- Draw bottom border of cells of non-last row and right border of cells of non-last column using grid background color
- 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屋!