У меня есть DataGridView.Я пытаюсь добавить строки к нему путем клонирования строки добавления новой строки.Когда я добавляю строку, я устанавливаю некоторые значения ее ячеек.Я пытаюсь получить доступ к экземплярам DataGridViewCell по имени их столбца.
Перед отображением пользовательского интерфейса я делаю нечто подобное в подклассе 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
Смежный вопрос здесь .
Я использую .NET Framework 4.6.1.
Обновление 1 :
Если изменить строку dgv.Columns.Add(c);
на
dgv.HandleCreated += (s, e) => { dgv.Columns.Add(c); };
, я получу следующее исключениев строке, которая начинается с MyRow r
:
System.ArgumentOutOfRangeException: 'Индекс был вне диапазона.Должен быть неотрицательным и меньшим, чем размер коллекции.Имя параметра: index '
Сведения об исключении:
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?Я пытался сделать это в конструкторе, но он не работает, даже с целочисленными индексами.Мне нужно это сделать, потому что я хочу иметь переставляемые столбцы.