1

我有一个显示用户列表的 WinForms DataGridView对话框。每行都包含一个 AD 用户组合框 ( DataGridViewComboboxColumn ),该组合框可以变得非常大(超过 10K 项)。此 DataGridView 用于将用户与其相应的 AD 用户链接。此组合框的内容不会在行之间更改。

出于性能原因,我想将此组合框更改为可以更好地扩展的东西。

我正在考虑使用一个带有小选择按钮的文本框。然后该按钮将打开一个用于选择 AD 用户的模式对话框。然后该单元格将包含选定的 AD-User 对象。或者,这个对话框也可以在单元格双击时打开,但我认为这不是很直观。

这将是替换此组合框的最佳选择吗?如果您有其他/更好的方法来处理此类选择,请告诉我。

如果是这样:如何创建这样的自定义 DataGridView-Cell (TextBox + Button)?

4

1 回答 1

1

最简单的解决方案是将列设为只读,然后使用按钮列。然后处理CellContentClick事件DataGridView以检测按钮点击。

另一种选择是创建基于 DataGridViewButtonColumn 的自定义列。像这样的东西有一点改变来显示单元格的值而不是标签文本。

您也可以通过自定义绘制单元格来实现它,而无需创建任何新的列类型,就像这样

例子

我的选择是从按钮列派生DataGridView以获得更好的用户体验,例如在鼠标移动时突出显示按钮。为此,我将更改此答案,该答案显示如何在单个单元格中呈现标签和按钮。在这里,我对其进行了一些更改,以将单元格值显示为标签文本:

在此处输入图像描述

using System.Drawing;
using System.Windows.Forms;
public class DataGridViewLookupColumn : DataGridViewButtonColumn
{
    public DataGridViewLookupColumn()
    {
        CellTemplate = new DataGridViewLookupCell();
        ButtonText = "...";
    }
    public string ButtonText { get; set; }
    public override object Clone()
    {
        var c = (DataGridViewLookupColumn)base.Clone();
        c.ButtonText = this.ButtonText;
        return c;
    }
}
public class DataGridViewLookupCell : DataGridViewButtonCell
{
    protected override void Paint(Graphics graphics, Rectangle clipBounds,
        Rectangle cellBounds, int rowIndex,
        DataGridViewElementStates elementState,
        object value, object formattedValue, string errorText,
        DataGridViewCellStyle cellStyle,
        DataGridViewAdvancedBorderStyle advancedBorderStyle,
        DataGridViewPaintParts paintParts)
    {
        var g = this.DataGridView;
        var c = (DataGridViewLookupColumn)this.OwningColumn;
        base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState,
            value, formattedValue, errorText, cellStyle, advancedBorderStyle,
            DataGridViewPaintParts.All &
            ~DataGridViewPaintParts.ContentBackground &
            ~DataGridViewPaintParts.ContentForeground);
        var cellRectangle = g.GetCellDisplayRectangle(c.Index, rowIndex, false);
        var buttonRectangle = GetContentBounds(rowIndex);
        var textRectangle = new Rectangle(cellRectangle.Location,
            new Size(cellRectangle.Width - GetButtonWidth(),
            cellRectangle.Height));
        buttonRectangle.Offset(cellRectangle.Location);
        var alignment = cellStyle.Alignment;
        cellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
        base.Paint(graphics, clipBounds, buttonRectangle, rowIndex, elementState,
            value, c.ButtonText, errorText, cellStyle, advancedBorderStyle,
            DataGridViewPaintParts.All &
            ~DataGridViewPaintParts.Border);
        cellStyle.Alignment = alignment;
        base.Paint(graphics, clipBounds, textRectangle, rowIndex, elementState,
             value, formattedValue, errorText, cellStyle, advancedBorderStyle,
             DataGridViewPaintParts.ContentForeground);
    }
    protected override Rectangle GetContentBounds(Graphics graphics,
        DataGridViewCellStyle cellStyle, int rowIndex)
    {
        var w = GetButtonWidth();
        var r = base.GetContentBounds(graphics, cellStyle, rowIndex);
        return new Rectangle(r.Right - w, r.Top, w, r.Height);
    }
    private int GetButtonWidth()
    {
        var c = (DataGridViewLookupColumn)this.OwningColumn;
        var text = c.ButtonText;
        return TextRenderer.MeasureText(text, c.DefaultCellStyle.Font).Width
            + 10 /*a bit padding */;
    }
}

手柄点击按钮

要处理按钮上的点击,请CellContentClick像正常一样处理DataGridViewColumnButton并检查是否e.RowIndex > -1e.ColumnIndex == your desired column index

void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    //if click is on row header or column header, do nothing.
    if(e.RowIndex < 0 || e.ColumnIndex < 0)
        return;

    //Check if click is on specific column 
    if( e.ColumnIndex  == dataGridView1.Columns["specific column name"].Index)
    {
        //Put some logic here, for example show a dialog and use result.
    }
}
于 2019-03-11T11:34:36.153 回答