如何用自定义标头替换DataGridView的HeaderCell? [英] How to replace the HeaderCells of a DataGridView with custom headers?
问题描述
当 DataSource
为以下内容时,何时使用自定义的 HeaderCell
(此处为 CustomDataGridViewColumnHeaderCell
)替换 DataGridViewColumnHeaderCell
(此处为: CustomDataGridViewColumnHeaderCell
)一个DataGridView已经设置为 DataTable
对象,并且还保留前一个HeaderCell的文本,该文本设置为DataTable的相应列的名称吗?
我有一个 DataGridView
的自定义标头类:
公共类CustomDataGridViewColumnHeaderCell:DataGridViewColumnHeaderCell{//将一个按钮添加到标题}
将 DataTable
设置为 DataSource
,将自动创建列.如何用自定义标头单元格替换上述默认标头单元格(上述实例)?
更多详细信息
要解决的问题是, DataGridView
需要在其标题单元格中嵌入可点击的按钮,箭头在上面的屏幕快照中指向.为此,有一个 CustomDataGridViewColumnHeaderCell
类.为了在 DataGridView
中显示数据,已将 DataTable
分配为其数据源.例如:
myDataGridView.DataSource = myDataTable;
完成此操作后, DataGridView
将具有与 DataTable
中的列相对应的列.我从默认的标题类派生了一个类,以便按钮显示在列标题内.
使用System.Drawing;使用System.Windows.Forms;DGVButtonHeaderCell类:DataGridViewColumnHeaderCell{公共只读Button按钮;私人填充m_ButtonPadding = Padding.Empty;公共DGVButtonHeaderCell(int buttonWidth = 40){button = new Button(){BackColor = Color.Orange,Width = buttonWidth};m_ButtonPadding =新的Padding(button.Width + 2,0,0,0);button.Click + = ButtonClick;}公共无效ReplaceHeaderCell(DataGridViewColumnHeaderCell previousHeader){如果(previousHeader == null)返回;SetStandardValues(previousHeader);var dgv = previousHeader.DataGridView;previousHeader.Dispose();dgv.Columns [previousHeader.OwningColumn.Index] .HeaderCell = this;}私人void SetStandardValues(DataGridViewColumnHeaderCell Previous){if(previous == null)返回;this.Style = previous.Style;button.Font = this.Style.Font?previous.DataGridView.ColumnHeadersDefaultCellStyle.Font;//ETC.}私人void ButtonClick(object sender,EventArgs e){OnClick(new DataGridViewCellEventArgs(ColumnIndex,RowIndex));MessageBox.Show(您单击了我");}受保护的重写void OnDataGridViewChanged(){如果(this.DataGridView == null)返回;this.DataGridView.Controls.Add(button);}受保护的重写void Paint(图形g,矩形clipBounds,矩形边界,int rowIndex,DataGridViewElementStates elementState,对象值,对象formattedValue,字符串errorText,DataGridViewCellStyle cellStyle,DataGridViewAdvancedBorderStyle advBorderStyle,DataGridViewPaintParts部件){cellStyle.Padding = Padding.Add(m_ButtonPadding,cellStyle.Padding);base.Paint(g,clipBounds,界限,rowIndex,elementState,值,formattedValue,errorText,cellStyle,advBorderStyle,部件);button.Location =新Point(bounds.Left,bounds.Top + 2);button.Height = bounds.Height-4;}受保护的覆盖无效void Dispose(布尔处置){如果(处置){button.MouseClick-= ButtonClick;button.Dispose();}base.Dispose(处置);}}
When to replace a DataGridViewColumnHeaderCell
with a custom HeaderCell
(here: CustomDataGridViewColumnHeaderCell
), when the DataSource
of a DataGridView is already set to a DataTable
object and also preserve the text of the previous HeaderCell, which is set to the name of the corresponding Column of the DataTable?
I have a custom header class for a DataGridView
:
public class CustomDataGridViewColumnHeaderCell : DataGridViewColumnHeaderCell
{
// adds a button to the header
}
A DataTable
is being set as the DataSource
, the Columns are created automatically. How can I replace the default header cells with custom header cells (instances of the above)?
More detail
The problem to solve is, a DataGridView
needs to have clickable buttons embedded in its header cells, where the arrow is pointing to in the screenshot above. For that, there is a class CustomDataGridViewColumnHeaderCell
. To show data in the DataGridView
, a DataTable
is being assigned as its data source. For example:
myDataGridView.DataSource = myDataTable;
After doing this, the DataGridView
will have columns corresponding to those in the DataTable
. I have derived a class from the default header classes, so that the buttons appear inside the column headers.
The HeaderCell of a DataGridViewColumn can be replaced at any time.
Even when the DataSource of the DataGridView is already set: in this case, you may want to set the Style of the current HeaderCell
to your new cell, in case some values need to be replicated (when the Column are auto-generated, there's probably not much to copy, but since the Style property can be set, let's set it).
In the example, I'm adding a ReplaceHeaderCell()
method to the custom HeaderCell
, which receives the instance of the current header, copies some properties then disposes of it before replacing the corresponding Column's HeaderCell
with itself.
If the Button we're adding to the HeaderCell
is a standard Button Control, this Control must be added to the DataGridView.Controls
collection (so it will be visible and brought to front).
If the Button is painted, overriding the Paint method, of course there's nothing to parent :).
Note: the Button is added in the OnDataGridViewChanged()
method override. This method is called each time a DataGridView object becomes the owner of the HeaderCell. When the Parent DataGridView changes, the Button is automatically added to its Controls collection.
► Here, the Paint method is overridden anyway: it's used to calculate the HeaderCell Text padding, so the Button won't overlap and hide the Column's text (this procedure needs to be fine-tuned, in relation to the Button's specifics).
To replace the current HeaderCell
of a Column (e.g., Column[0]
), just create a new instance of the custom HeaderCell
and call the ReplaceHeaderCell()
method, passing the reference of the HeaderCell
to replace:
var newButtonHeaderCell = new DGVButtonHeaderCell();
newButtonHeaderCell.ReplaceHeaderCell(dataGridView1.Columns[0].HeaderCell);
This is how it works:
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;
previousHeader.Dispose();
dgv.Columns[previousHeader.OwningColumn.Index].HeaderCell = this;
}
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的HeaderCell?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!