您遇到的问题是 DataTable 不是 IEnumerable 类,这意味着您将无法在其上使用 Linq 方法。这就是编译器所抱怨的;您编写的 Linq 查询被编译为一系列方法调用,编译器希望找到一个 Where() 方法,它可以在 DataTable 上调用该方法来执行 where 子句的过滤,但没有找到。
但是,它的 Rows 属性是 IEnumerable(但不是通用的,因此您需要使用 OfType() 方法来创建 DataRows 的 IEnumerable):
from r in itemDetails.Rows.OfType<DataRow>()
where r.ItemName == dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString()
select r.ItemID;
现在,除此之外,DataRow 没有属性 ItemName 和 ItemID。您不会以这种方式从 DataRow 获取值。编译器(还)没有在您的代码中抱怨这一点,因为它甚至不知道类型r
是什么,因此它无法确定该类型的对象是否具有这些成员。一旦你指定 r 是一个 DataRow,编译器就会发现额外的错误。
要解决这个问题,您需要使用 DataRow 上可用的索引器。您可以按索引(从左到右从零开始,基于水合数据表的查询的选择列表)或按列名(再次基于列的名称或您给它们的别名)引用列在选择列表中):
from r in itemDetails.Rows.OfType<DataRow>()
where r["ItemName"].ToString() == dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString()
select (int)r["ItemID"];
索引器生成的项目是 Object 类型的;您需要将它们强制转换或转换为正确的类型(例如,我假设 ItemName 是一个字符串,而 ItemId 是一个 32 位整数)。
至于您的第二个问题,DataGridViews 不会公开其包含的控件的大部分事件。相反,这些控件被挂钩,并导致 DGV 触发您可以处理的自己的事件。查看 CellValueChanged 事件和/或 CellDirtyStatusChanged 事件。当用户更改单元格的值然后该单元格失去焦点时,将引发第一个。在实际发生提交之前,一旦对单元格的值进行第一次更改,就会引发 CellDirtyStatusChanged。