【问题标题】:Change values of Cells in a Filtered DataGridView更改过滤的 DataGridView 中单元格的值
【发布时间】:2021-03-10 08:54:57
【问题描述】:

我的 DataGridView 有一个名为 flag 的列和其他列。
当我应用过滤器时:

dataGridView2.DataSource = 
    new DataView(ds, "flag = 1", "tw_Name DESC", DataViewRowState.CurrentRows);

它仅显示列 flag 值等于 1 的行,但是...
当我尝试以编程方式更改此值时,例如在 6 个选中的行中:

foreach (DataGridViewRow row in dataGridView2.Rows)
{
    if (Convert.ToBoolean(row.Cells["zazn"].Value))
    {
        row.Cells["flags"].Value = 0;
    }
}

三行消失,一行改变其值,两行不变。
接下来,当我单击任意行时,我只会得到 2 个所需的更改。

【问题讨论】:

  • 您是否正在重置数据源以应用过滤器? -- 看起来你的 DGV DataSource 是一个 DataTable,然后,应用过滤器和排序:var dv = (dataGridView2.DataSource as DataTable).DefaultView; dv.RowFilter = "flag = 1"; dv.Sort = "tw_Name DESC";
  • 是的,DataSource 是一个 DataTable。我应用过滤器并像 Jimi 写的那样排序,但问题是一样的

标签: c# winforms filter datagridview


【解决方案1】:

由于您使用的是 DataTable,因此最好在 DataTable 的 DataView 上的过滤器处于活动状态时修改其 Rows 内容的值,而不是 DataGridView 单元格。

这会导致数据更改的立即传播,您的 DataGridView 将确认。如果您执行相反的操作,则无法保证将控件的更改传播到数据源。
这可能违背了 Control 用来通知其 DataSource 更改的内部机制:在 Cell 编辑完成并执行验证后,DataGridView 通知其 Cells 的值更改。

您可以尝试调用[DataGridView].EndEdit() 和Validate(),这并不意味着在任何情况下Control 和DataSource 都会在您期望的时候同步。


设置过滤器并对视图排序:

  • 请注意,订单应用于 DefaultView,而不是 DataTable。 DataTable 中的行顺序保持不变。

在您的示例代码中,过滤器设置为flag = 1,而您在row.Cells["flags"] 中为列使用另一个名称。

var dView = (dataGridView2.DataSource as DataTable).DefaultView;
dView.RowFilter = "flag = 1";
dView.Sort = "tw_Name DESC";

当您需要更改某些行中的值时,请使用 DataGridView.DataSource 访问 DataTable 并将其转换为 DataTable(或 BindingSouce 或您使用的任何其他数据源)。
您现在可以循环 DataRows 并根据条件为某些 Columns 设置新值,如本例所示:

var dt = dataGridView2.DataSource as DataTable;

for (int i = 0; i <= dt.Rows.Count - 1; i++) {
    var row = dt.Rows[i];
    if (row["zazn"] != DBNull.Value && (bool)row["zazn"]) {
        row["flag"] = 0;
    }
}

你可以使用DataGridView.Row.DataBoundItem做同样的事情,在这种情况下是一个DataRowView,向后循环(只循环可见的行):

var dt = dataGridView2.DataSource as DataTable;

//BACKWARDS - also assuming there's a NewRow, so Rows.Count - 2
for (int i = dataGridView2.Rows.Count - 2; i >= 0; i--) {
    var row = (dataGridView2.Rows[i].DataBoundItem as DataRowView).Row;
    if (row["zazn"] != DBNull.Value && (bool)row["zazn"]) {
        row["flag"] = 0;
    }
}

如果你做同样的事情但使用前向循环:

for (int i = 0; i < dataGridView2.Rows.Count - 1; i++) { ... }

你的情况和以前一样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-19
    • 1970-01-01
    相关资源
    最近更新 更多