如何创建一个新的DataGridViewRow并使用列名而不是索引指定值?

时间:2018-11-29 13:26:13

标签: c# winforms datagridview datagridviewcolumn

我有一个DataGridView。我尝试通过克隆add-new-row行来向其中添加行。当添加一行时,我设置了其单元格的一些值。我尝试通过其列的名称访问DataGridViewCell实例。

在显示UI之前,我在DataGridView的子类中做了类似的事情:

MyDataGridViewRow r = Rows[NewRowIndex].Clone() as MyDataGridViewRow;
Rows.Add(r);
r.Cells[Columns["MyColumnName"].Index].Value = "Example text";

这行不通,因为我(在最后一行)收到此异常:

  

System.ArgumentOutOfRangeException:'指定的参数超出了   有效值范围。参数名称:rowIndex'

我想单元格将添加到相应的列,而不是添加到行。

如果我直接将DataGridViewRow.Cells[]运算符与列名Tag一起使用:

  

System.ArgumentException:'找不到名为Tag的列。参数   名称:columnName'

发生这种情况时,我在调试器中看到Cells集合包含所有列,每个Cell都有

  • 如果我在ColumnIndex之前尝试使用RowIndex运算符,则-1[]等于Rows.Add,并且
  • 如果我在RowIndex运算符之前调用-1,则只有Rows.Add等于[](在这种情况下,ColumnIndex的值从0开始)。

这发生在显示任何形式之前。

因此,我试图制作一个具有相同错误的小项目。这在Form1类中:

DataGridView dgv;

public Form1()
{
    InitializeComponent();

    dgv = new DataGridView();

    // from DataGridView subclass ctor
    dgv.RowTemplate = new MyRow();

    dgv.Left = 10;
    dgv.Top = 10;
    Controls.Add(dgv);

    // from Initialize method
    dgv.Columns.Clear();
    DataGridViewTextBoxColumn c = new DataGridViewTextBoxColumn()
    {
        HeaderText = "My Header",
        Name = "MyColumn"
    };
    dgv.Columns.Add(c);

    // here the columns and row templates should be ready
    MyRow r = dgv.Rows[dgv.NewRowIndex].Clone() as MyRow;
    r.Cells["MyColumn"].Value = "My Value";
    dgv.Rows.Add(r);
}

internal class MyRow : DataGridViewRow
{
    internal MyRow() : base()
    {
    }
}

现在我在行dgv.Columns.Add(c)上遇到另一个异常:

  

System.MissingMethodException:'未定义无参数构造函数   为此对象。”

例外情况:

System.MissingMethodException
  HResult=0x80131513
  Message=No parameterless constructor defined for this object.
  Source=mscorlib
  StackTrace:
   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Activator.CreateInstance(Type type)
   at System.Windows.Forms.DataGridViewRow.Clone()
   at System.Windows.Forms.DataGridView.get_RowTemplateClone()
   at System.Windows.Forms.DataGridViewRowCollection.AddInternal(Boolean newRow, Object[] values)
   at System.Windows.Forms.DataGridView.AddNewRow(Boolean createdByEditing)
   at System.Windows.Forms.DataGridView.OnColumnCollectionChanged_PostNotification(DataGridViewColumn dataGridViewColumn)
   at System.Windows.Forms.DataGridViewColumnCollection.OnCollectionChanged_PostNotification(CollectionChangeEventArgs ccea, Boolean changeIsInsertion, Point newCurrentCell)
   at System.Windows.Forms.DataGridViewColumnCollection.Add(DataGridViewColumn dataGridViewColumn)
   at project_namespace.Form1..ctor() in {project folder path here}\Form1.cs:line 37
   at project_namespace.Program.Main() in {project folder path here}\Program.cs:line 19

相关问题here

我正在使用.NET Framework 4.6.1。

更新1

如果我将dgv.Columns.Add(c);行更改为

dgv.HandleCreated += (s, e) => { dgv.Columns.Add(c); };

MyRow r开头的行上出现以下异常:

  

System.ArgumentOutOfRangeException:'索引超出范围。一定是   非负数且小于集合的大小。参数名称:   索引”

异常详细信息:

System.ArgumentOutOfRangeException
  HResult=0x80131502
  Message=Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
  Source=mscorlib
  StackTrace:
   at System.Collections.ArrayList.get_Item(Int32 index)
   at System.Windows.Forms.DataGridViewRowCollection.SharedRow(Int32 rowIndex)
   at System.Windows.Forms.DataGridViewRowCollection.get_Item(Int32 index)
   at cs_test_6.Form1..ctor() in .....\Form1.cs:line 45
   at cs_test_6.Program.Main() in .....\Program.cs:line 19

如果我删除了构造函数中的最后三行,则在单行匿名函数中,现在在dgv.Columns.Add(c)的行上会遇到相同的第一个错误。

更新2 :我学到的东西:

  • 行模板类必须具有公共构造函数;
  • 行应在列之后添加;
  • 我可以使用带有某些属性的行模板类来按名称设置列,但是我仍然不清楚;

如果我从文件中加载列的顺序,并且可以对其进行重新排序,那么如何使用行模板按名称设置单元格的值?这段代码就像Rows.Add(val1, val2)一样工作(但可能效率较低):

MyDataGridViewRow r = new MyDataGridViewRow()
{

};
r.CreateCells(this);
r.Cells[0] =
    new DataGridViewTextBoxCell()
    {
        Value = val1
    };
r.Cells[1] =
    new DataGridViewTextBoxCell()
    {
        Value = val2
    };
Rows.Add(r);

如果我尝试使用r.Cells["MyColumn"],则会收到问题开头显示的错误。

我的问题是:如何以及何时可以通过DataGridViewRow的子类中的列名引用单元格?我尝试在构造函数中执行此操作,但它不起作用,即使使用整数索引也是如此。我需要这样做,因为我想拥有可重新排序的列。

0 个答案:

没有答案