c# - 从 DataTable 绑定的 DataGridView 中删除选定的行
问题描述
考虑一个DataGridView
是DataSource
一个DataTable
。dataGridView 允许一次选择一行。有一个“删除”按钮,它应该从绑定的数据表中删除选定的行,按其中一列。
从用户的角度来看,我已将其配置DataGridView
为不可编辑。应该只能通过Button
我创建的单独的“删除”来删除一行(从数据表和网格中)。事件处理程序如下所示:
private void delete_Click(object sender, EventArgs args)
{
var usersTable = myGridView.DataSource as DataTable;
foreach (DataGridViewRow selected in myGridView.SelectedRows)
{
string name = (string)selectedRow.Cells[0].Value;
foreach (DataRow tableRow in usersTable.Rows)
{
if (tableRow["Name"].ToString().Equals(name))
tableRow.Delete();
}
usersTable.AcceptChanges();
}
myGridView.DataSource = usersTable;
}
如何正确执行此操作,而不会出现“集合已修改,枚举可能无法执行”错误?
网格填充如下:
private DataTable usersTable = new DataTable("Users");
void Populate()
{
usersTable.Columns.Clear();
usersTable.Rows.Clear();
usersTable.Columns.Add("Name", typeof(string));
// addd other columns...
foreach (var user in usersCollection)
{
usersTable.Rows.Add(user.GetName()),
// add other rows...
}
// bind the data
myGridView.DataSource = usersTable;
}
解决方案
... dataGridView 允许一次选择一行...这应该删除选定的行,通过其中一列...
DataGridView.SelectedRows属性要求将DataGridView.SelectionMode设置为FullRowSelect
或RowHeaderSelect
返回选定的行。应该选择整行,而不仅仅是RowHeaderSelect
选项中的某些单元格。阅读属性的备注部分。
在这种情况下,您可以像这样删除选定的行:
private void delete_Click(object sender, EventArgs e)
{
if (myGridView.SelectedRows.Count > 0 && !myGridView.SelectedRows[0].IsNewRow))
{
myGridView.Rows.Remove(myGridView.SelectedRows[0]);
// Don't call this if you have a DB to update.
// (myGridView.DataSource as DataTable).AcceptChanges();
}
}
或者,如果您DataGridView.MultiSelect
启用了该属性:
private void delete_Click(object sender, EventArgs e)
{
if (myGridView.SelectedRows.Count > 0)
{
foreach (var r in myGridView.SelectedRows
.Cast<DataGridViewRow>()
.Where(r => !r.IsNewRow))
myGridView.Rows.Remove(r);
// Don't call this if you have a DB to update.
// (myGridView.DataSource as DataTable).AcceptChanges();
}
}
现在,如果您将SelectionMode
属性设置为其他值之一,那么您不能指望该SelectedRows
属性。您需要通过DataGridView.SelectedCellsSelectionMode
获取选定的行,无论属性值如何,它总是填充。评论
private void delete_Click(object sender, EventArgs e)
{
var selRows = myGridView.SelectedCells
.Cast<DataGridViewCell>()
.Where(c => !c.OwningRow.IsNewRow)
.Select(c => c.OwningRow)
.Distinct();
foreach (var r in selRows)
myGridView.Rows.Remove(r);
// Don't call this if you have a DB to update.
// (myGridView.DataSource as DataTable).AcceptChanges();
}
或者,通过DataGridViewRow.DataBoundItem属性从所选行中获取DataRow对象,并将它们从.DataTable
private void delete_Click(object sender, EventArgs e)
{
var dt = myGridView.DataSource as DataTable;
var selRows = myGridView.SelectedCells
.Cast<DataGridViewCell>()
.Where(c => !c.OwningRow.IsNewRow)
.Distinct()
.Select(c => ((DataRowView)c.OwningRow.DataBoundItem).Row);
foreach (var r in selRows)
dt.Rows.Remove(r);
// Don't call this if you have a DB to update.
// dt.AcceptChanges();
}
重要的
正如@Jimi 评论的那样,如果您的项目中有一个数据库,那么DataTable.AcceptChanges方法应该只在之后调用:
- 填充
DataTable
,从数据库中加载数据。 - 提交更改,更新数据库。
推荐阅读
- r - 如何在 forest_model 中将换行符添加到因子级别
- nginx - 如何将 nginx 配置为反向代理服务器 /some-path 从另一个服务器根路径 /
- linux - 按大小降序从 Tar 存档中提取 3 个最小的文件
- omnet++ - RSU 在静脉中的簇
- android - Spinner 中的项目可见但 onItemSelected 不起作用
- c++ - 在 Xubuntu 19.04 中编译 c++ 是否应该与在 Ubuntu 18.04 中编译 c++ 不同
- javascript - 在 HTML5UP 主题“镜头”中使用视频
- c# - WPF - 在 ListView 中禁用按钮时的奇怪行为
- postgresql - 在 PostgreSQL 中检查组内的条件
- .htaccess - 我在typo3中找不到htaccess