所以在填充我的datagridview时,我通常会做类似的事情
public void FillTable(CoBRAMetaField[] metaFields)
{
dataGridView.Rows.Clear();
// do something with metaFields
}
重要提示:
CoBRAMetaField
是具有ID和其他内容的对象
网格中的每一行都包含一个元字段对象
我的网格正确填充了(抱歉,语言是德语)
当我再次填充网格时,我只想删除新metaFields数组中不存在的带有metaFields的行。我想要这种行为,因为当用户为该行选择一个值时,我不希望其被删除并再次创建,因为选择的值也将被删除。
我想到了这个
public void FillTable(CoBRAMetaField[] metaFields)
{
for (int i = 0; i < dataGridView.Rows.Count; i++) // loop through the grid rows
{
double metaFieldID = (dataGridView.Rows[i].Cells[0].Tag as CoBRAMetaField).ID; // get the ID from the row metaField
if (metaFields.Any(field => field.ID == metaFieldID)) // Does it exist?
metaFields = metaFields.Where(field => field.ID != metaFieldID).ToArray(); // Remove it from the new array
else // it doesn't exist
dataGridView.Rows.Remove(dataGridView.Rows[i]); // remove the row
}
// Fill the grid with the remaining metaFields
}
第一次运行已正确初始化
第二轮运行似乎崩溃,某些字段保持空白
当我按下该行上的按钮时,我得到一个nullpointer异常。我仅在使用“新代码”时收到此错误,所以我缺少什么吗?有什么我没想到的吗?
我将在此处提供完整的示例
首先,在表单上创建一个DataGridView
和Button
。为所有必需的类创建一个文件,并使用此代码段
之后,在表单代码中填充一些测试数据
现在设置DataGridView
逻辑
我添加了
dataGridView.AllowDrop = false;
dataGridView.AllowUserToAddRows = false;
dataGridView.AllowUserToDeleteRows = false;
dataGridView.AllowUserToOrderColumns = false;
dataGridView.AllowUserToResizeRows = false;
如果您只想复制粘贴,但也可以由表单设计者执行。看一下dataGridView.Rows.Clear();
,它提供了一个有效的示例。 注释掉并使用上面的代码测试错误的示例
答案 0 :(得分:5)
主要问题在于添加行的代码(来自链接):
// Fill the grid with the remaining metaFields
for (int i = 0; i < metaFields.Length; i++)
{
MetaField currentMetaField = metaFields[i];
dataGridView.Rows.Add(currentMetaField.Name, null);
DataGridViewRow newRow = dataGridView.Rows[i]; // <-- Problem!
DataGridViewCell metaFieldCell = newRow.Cells[0];
metaFieldCell.Tag = currentMetaField;
(newRow.Cells[1] as DataGridViewAllocationCell).Initialize(releaseSetupData);
}
在标记的行中,您假定添加的行的索引与i
相同,当您从空网格开始时为true,在更新网格并保留一些旧记录时则为true
处理它的正确方法是不假定新的行索引-它是由Add方法返回的:
int rowIndex = dataGridView.Rows.Add(currentMetaField.Name, null);
DataGridViewRow newRow = dataGridView.Rows[rowIndex];
这将解决问题的原始问题。
代码的删除部分还存在一个问题-for
循环将丢失对已删除行旁边的行的检查。每当您要迭代某些列表并在迭代过程中删除项目时,请使用 reverse for
循环和RemoveAt
:
for (int i = dataGridView.Rows.Count - 1; i >= 0; i--) // <--
{
double metaFieldID = (dataGridView.Rows[i].Cells[0].Tag as MetaField).ID;
if (metaFields.Any(field => field.ID == metaFieldID))
metaFields = metaFields.Where(field => field.ID != metaFieldID).ToArray();
else
dataGridView.Rows.RemoveAt(i); // <--
}
可以进一步改善删除代码(目前对于这些Any
,Where
+ ToArray
而言效率低下),但至少通过上述更改,它可以正常工作。