【问题标题】:Windows Forms DataGridView control have different control types in the same columnWindows 窗体 DataGridView 控件在同一列中有不同的控件类型
【发布时间】:2009-06-12 11:46:48
【问题描述】:

是否可以在 DataGridView 中执行以下操作:

在同一列中我想在DataGridViewTextBoxColumn和DataGridViewComboBoxColumn之间更改每一行的控件类型?

(这是因为有时我想显示一个下拉列表,而其他时候我只想让用户输入一个手绘值)。

谢谢,

附:我正在使用 C#

【问题讨论】:

  • 非常好的问题。使用 DataGridView 类时遇到这个问题只是时间问题。

标签: c# winforms datagridview


【解决方案1】:

我最近有一个类似的用例,最后写了类似下面的代码:

编写自定义的 Cell 和 Column 类,并覆盖单元格上的 EditType 和 InitializeEditingControl 方法,以根据需要返回不同的控件(这里我只是将数据绑定到自定义类的列表,其中 .useCombo 字段指示要使用的控件使用):

// Define a column that will create an appropriate type of edit control as needed.
public class OptionalDropdownColumn : DataGridViewColumn
{
    public OptionalDropdownColumn()
        : base(new PropertyCell())
    {
    }

    public override DataGridViewCell CellTemplate
    {
        get
        {
            return base.CellTemplate;
        }
        set
        {
            // Ensure that the cell used for the template is a PropertyCell.
            if (value != null &&
                !value.GetType().IsAssignableFrom(typeof(PropertyCell)))
            {
                throw new InvalidCastException("Must be a PropertyCell");
            }
            base.CellTemplate = value;
        }
    }
}

// And the corresponding Cell type
public class OptionalDropdownCell : DataGridViewTextBoxCell
{

    public OptionalDropdownCell()
        : base()
    {           
    }

    public override void InitializeEditingControl(int rowIndex, object
        initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
    {
        // Set the value of the editing control to the current cell value.
        base.InitializeEditingControl(rowIndex, initialFormattedValue,
            dataGridViewCellStyle);

        DataItem dataItem = (DataItem) this.OwningRow.DataBoundItem;
        if (dataItem.useCombo)
        {
            DataGridViewComboBoxEditingControl ctl = (DataGridViewComboBoxEditingControl)DataGridView.EditingControl;
            ctl.DataSource = dataItem.allowedItems;
            ctl.DropDownStyle = ComboBoxStyle.DropDownList;
        }
        else
        {
            DataGridViewTextBoxEditingControl ctl = (DataGridViewTextBoxEditingControl)DataGridView.EditingControl;
            ctl.Text = this.Value.ToString();
        }
    }

    public override Type EditType
    {
        get
        {
            DataItem dataItem = (DataItem)this.OwningRow.DataBoundItem;
            if (dataItem.useCombo)
            {
                return typeof(DataGridViewComboBoxEditingControl);
            }
            else
            {
                return typeof(DataGridViewTextBoxEditingControl);
            }
        }
    }
}

然后只需在你的这种类型的DataGridView中添加一列,就应该使用正确的编辑控件。

【讨论】:

  • +1,这对我来说看起来非常有用和干净。很酷的一点是,它只是在 EditType getter 中“及时”发出所需的编辑控件类的信号,让 Grid 完成艰苦的工作,并通过引用 DataGridView.EditingControl 来使用如此创建的编辑控件。
【解决方案2】:

您可以创建自己的继承自 DataGridViewCell 的类,并覆盖足够的虚拟成员(InitializeEditingControls、EditType,也许还有其他一些)。然后,您可以使用此类的实例作为单元格模板创建 DataGridViewColumn

【讨论】:

  • 谢谢。看起来是正确的轨道。不幸的是,我对此很陌生,无论我做什么,我都无法让细胞出现。我已经按照建议覆盖了 EditType。如果我从“DataGridViewTextBoxCell”继承,那么我可以看到该单元格,从“DataGridViewCell”继承并覆盖 EditType 以返回 typeof(DataGridViewTextBoxEditingControl) 给我一个空白单元格 - 我可以看到该列。我确信我遗漏了一些明显的东西。
  • 似乎视图模式控件没有显示或宽度为零?我可以切换到控件,按 F2 并键入一个值。当我退出时我看不到它,当我返回编辑模式时它仍然存在。
  • 我认为你还需要重写 PositionEditingPanel 和 PositionEditingControl。但我自己从来没有做过,所以我只能猜测......你应该使用 Reflector 来看看标准 DataGridViewCells 的代码,它可能会告诉你你需要做什么
  • -1 -- 我很想知道这是否有帮助,以及解决方案是什么样的。因为:这个答案只是对“如何创建自定义列”的简要描述。例如 InitializeEditingControl 会是什么样子?您必须执行 TextBoxCell 或 ComboBoxCell 版本的方法——但由于您的自定义单元格只能从其中一个继承,您必须从另一个类复制代码。而且我认为在自定义单元格中创建两个代表是不可行的,因为它们不会正确链接到单元格/列。
  • @TheBlastOne,好吧,答案被接受了,所以我想这还不错,值得一票否决...
【解决方案3】:

您可以创建一个包含两个控件的模板列,隐藏不需要的一个,然后在代码中将另一个绑定到数据源。

【讨论】:

    猜你喜欢
    • 2011-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-15
    • 2011-05-24
    • 2012-09-18
    相关资源
    最近更新 更多