c# - 清除datagridview重复行并保留唯一行
问题描述
所以在填充我的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
}
第一次运行被正确初始化
第二次运行似乎崩溃了,一些字段仍然是空的
当我按下这一行上的按钮时,我得到一个空指针异常。我只有在使用“新代码”时才会收到这个错误,所以我错过了什么吗?有什么我没有想到的吗?
我将在这里提供一个完整的例子
首先在窗体上创建一个DataGridView
和。Button
为所有必需的类创建一个文件并获取此代码段
之后用一些测试数据填写表单代码
现在设置DataGridView
逻辑
我添加了
dataGridView.AllowDrop = false;
dataGridView.AllowUserToAddRows = false;
dataGridView.AllowUserToDeleteRows = false;
dataGridView.AllowUserToOrderColumns = false;
dataGridView.AllowUserToResizeRows = false;
如果您只想复制粘贴,但您也可以通过表单设计器来完成。看看dataGridView.Rows.Clear();
这提供了一个工作示例。将其注释掉并使用上面的代码来测试不正确的示例
解决方案
主要问题在于添加行的代码(取自链接):
// 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
,当您从空网格开始时这是正确的,当网格更新并保留一些旧记录时则不是。
处理它的正确方法是不假定新的行索引 - 它由Add方法返回:
int rowIndex = dataGridView.Rows.Add(currentMetaField.Name, null);
DataGridViewRow newRow = dataGridView.Rows[rowIndex];
这将解决问题的原始问题。
代码的删除部分还有一个问题——for
循环将错过检查已删除行旁边的行。每当您想在迭代期间迭代某些列表并删除项目时,请使用反向 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
),但至少通过上述更改它可以正常工作。
推荐阅读
- python - 如何使用 Beautiful Soup 从特定的 div 类中提取文本?
- database - 使用 Firebase 和 Flutter 构建聊天应用程序的最简单方法是什么
- jenkins - 从属性中的 GroovyScript 内部访问 jenkins env 参数
- reactjs - 反应路由器允许带点(。)的路径
- syntax - 如何在 Tcl 中粘贴文字
- excel - 如何用Excel对单个单元格的括号包围的多个数字求和?
- git - 如何将主分支合并到我当前的分支
- android - 如何使用改造和 gson 转换器将嵌套的 JSON 扁平化为单个类?
- c# - 如何对这个函数进行单元测试
- javascript - 我如何将按钮单击事件与 vuetify 数据表中一行内的行单击事件分开