如何用自定义标题替换 DataGridView 的 HeaderCells?
Posted
技术标签:
【中文标题】如何用自定义标题替换 DataGridView 的 HeaderCells?【英文标题】:How to replace the HeaderCells of a DataGridView with custom headers? 【发布时间】:2020-07-21 05:31:42 【问题描述】:当 DataGridView 的 DataSource
已设置为 DataTable
对象并保留前一个 HeaderCell 的文本时,何时将 DataGridViewColumnHeaderCell
替换为自定义 HeaderCell
(此处为:CustomDataGridViewColumnHeaderCell
) ,设置为DataTable对应Column的名称?
我有一个DataGridView
的自定义标头类:
public class CustomDataGridViewColumnHeaderCell : DataGridViewColumnHeaderCell
// adds a button to the header
DataTable
被设置为DataSource
,自动创建列。如何用自定义标题单元格替换默认标题单元格(上述实例)?
更多细节
要解决的问题是,DataGridView
需要在其标题单元格中嵌入可点击按钮,箭头在上面的屏幕截图中指向。为此,有一个类CustomDataGridViewColumnHeaderCell
。为了在DataGridView
中显示数据,DataTable
被指定为其数据源。例如:
myDataGridView.DataSource = myDataTable;
完成此操作后,DataGridView
的列将与DataTable
中的列相对应。我从默认标题类派生了一个类,以便按钮出现在列标题内。
【问题讨论】:
您能详细说明一下吗。到底是在做什么。 @BheemsenSingh 我会在帖子中添加更多细节。 @MongZhu 我想你误会了。简而言之,当我分配DataTable
时,我希望列标题类型为CustomDataGridViewColumnHeaderCell : DataGridViewColumnHeaderCell
,而不是默认的DataGridViewColumnHeaderCell
,但标题名称仍与DataTable
相对应。
您是否尝试过遍历列集合并将其替换为自定义列?
其实有一个点击事件可以用来处理这个工作。
【参考方案1】:
DataGridViewColumn 的HeaderCell 可以随时替换。
即使已经设置了 DataGridView 的数据源:在这种情况下,您可能希望将当前 HeaderCell
的样式设置为新单元格,以防需要复制某些值(当列是自动-生成,可能没有太多要复制的,但是既然可以设置Style属性,那就设置吧)。
在示例中,我向自定义 HeaderCell
添加了一个 ReplaceHeaderCell()
方法,该方法接收当前标头的实例,复制一些属性,然后在替换相应的之前处理它列的HeaderCell
本身。
如果我们添加到HeaderCell
的按钮是标准按钮控件,则必须将此控件添加到DataGridView.Controls
集合中(这样它才会可见并放在前面)。
如果 Button 被绘制,覆盖Paint method,当然没有任何父项:)。
注意: Button 是在 OnDataGridViewChanged()
方法覆盖中添加的。每次 DataGridView 对象成为 HeaderCell 的所有者时都会调用此方法。当 Parent DataGridView 发生变化时,Button 会自动添加到其 Controls 集合中。
► 在这里,Paint 方法无论如何都会被覆盖:它用于计算 HeaderCell 文本填充,因此 Button 不会重叠并隐藏 Column 的文本(此过程需要根据 Button 的细节进行微调)。
要替换列的当前HeaderCell
(例如Column[0]
),只需创建自定义HeaderCell
的新实例并调用ReplaceHeaderCell()
方法,传递HeaderCell
的引用来替换:
var newButtonHeaderCell = new DGVButtonHeaderCell();
newButtonHeaderCell.ReplaceHeaderCell(dataGridView1.Columns[0].HeaderCell);
这就是它的工作原理:
using System.Drawing;
using System.Windows.Forms;
class DGVButtonHeaderCell : DataGridViewColumnHeaderCell
public readonly Button button;
private Padding m_ButtonPadding = Padding.Empty;
public DGVButtonHeaderCell(int buttonWidth = 40)
button = new Button() BackColor = Color.Orange, Width = buttonWidth ;
m_ButtonPadding = new Padding(button.Width + 2, 0, 0, 0);
button.Click += ButtonClick;
public void ReplaceHeaderCell(DataGridViewColumnHeaderCell previousHeader)
if (previousHeader == null) return;
SetStandardValues(previousHeader);
var dgv = previousHeader.DataGridView;
dgv.Columns[previousHeader.OwningColumn.Index].HeaderCell = this;
previousHeader.Dispose();
private void SetStandardValues(DataGridViewColumnHeaderCell previous)
if (previous == null) return;
this.Style = previous.Style;
button.Font = this.Style.Font ?? previous.DataGridView.ColumnHeadersDefaultCellStyle.Font;
// etc.
private void ButtonClick(object sender, EventArgs e)
OnClick(new DataGridViewCellEventArgs(ColumnIndex, RowIndex));
MessageBox.Show("You clicked me");
protected override void OnDataGridViewChanged()
if (this.DataGridView == null) return;
this.DataGridView.Controls.Add(button);
protected override void Paint(Graphics g, Rectangle clipBounds, Rectangle bounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advBorderStyle, DataGridViewPaintParts parts)
cellStyle.Padding = Padding.Add(m_ButtonPadding, cellStyle.Padding);
base.Paint(g, clipBounds, bounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advBorderStyle, parts);
button.Location = new Point(bounds.Left, bounds.Top + 2);
button.Height = bounds.Height - 4;
protected override void Dispose(bool disposing)
if (disposing)
button.MouseClick -= ButtonClick;
button.Dispose();
base.Dispose(disposing);
【讨论】:
以上是关于如何用自定义标题替换 DataGridView 的 HeaderCells?的主要内容,如果未能解决你的问题,请参考以下文章
Cordova android - 如何用生成的替换自定义 build.gradle