winforms 如何用自定义头替换DataGridView的HeaderCells?

pobjuy32  于 2023-06-06  发布在  其他
关注(0)|答案(1)|浏览(443)

何时将DataGridViewColumnHeaderCell替换为自定义HeaderCell(此处:CustomDataGridViewColumnHeaderCell),当DataGridView的DataSource已经设置为DataTable对象,并且还保留了前一个HeaderCell的文本,该文本设置为DataTable的相应列的名称时?
我有一个DataGridView的自定义头类:

public class CustomDataGridViewColumnHeaderCell : DataGridViewColumnHeaderCell
{
    // adds a button to the header
}

DataTable被设置为DataSource,列将自动创建。如何用自定义标题单元格替换默认标题单元格(上述示例)?

更多详情

要解决的问题是,DataGridView需要在其标题单元格中嵌入可单击的按钮,上面的截图中箭头指向的位置。有一个类CustomDataGridViewColumnHeaderCell。为了显示DataGridView中的数据,将DataTable指定为其数据源。例如:

myDataGridView.DataSource = myDataTable;

完成此操作后,DataGridView将具有与DataTable中的列对应的列。我从默认的标题类派生了一个类,这样按钮就出现在列标题中。

q1qsirdb

q1qsirdb1#

DataGridViewColumn的HeaderCell可以随时替换。
即使已经设置了DataGridView的DataSource:在这种情况下,您可能希望将当前HeaderCell的Style设置为新单元格,以防某些值需要复制(当Column是自动生成的时,可能没有太多需要复制的内容,但由于可以设置Style属性,因此让我们设置它)。
在这个例子中,我将一个**ReplaceHeaderCell()**方法添加到自定义的HeaderCell中,它接收当前头部的示例,复制一些属性,然后在用它自己替换相应的Column的HeaderCell之前处理它。
如果我们要添加到HeaderCell的Button是一个标准的Button Control,则必须将此Control添加到DataGridView.Controls集合中(因此它将可见并置于最前面)。
如果Button被绘制,覆盖了Paint method,当然没有什么可以作为父对象:)。

**注意:Button是在OnDataGridViewChanged()**方法覆盖中添加的。每当DataGridView对象成为HeaderCell的所有者时,都会调用此方法。当ParentDataGridView更改时,Button将自动添加到其Controls集合中。

►在这里,Paint方法无论如何都被覆盖:它用于计算HeaderCell文本填充,因此Button不会重叠和隐藏Column的文本(此过程需要根据Button的具体情况进行微调)。
要替换Column的当前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;
        Style = previous.Style;
        button.Font = 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 (DataGridView == null) return;
        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);
    }
}

相关问题