あなたが抱えている問題は、DataTable が IEnumerable クラスではないことです。つまり、Linq メソッドを使用できないということです。それがコンパイラの不満です。作成した Linq クエリは、一連のメソッド呼び出しにコンパイルされます。コンパイラは、DataTable で呼び出して where 句のフィルタリングを実行できる 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 で利用可能なインデクサーを使用する必要があります。列は、インデックス (DataTable をハイドレートしたクエリの選択リストに基づいて左から右へゼロベース) または列名 (列の名前または指定したエイリアスに基づく) のいずれかで参照できます。選択リストで):
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 ビット整数であると想定しています)。
2 番目の質問については、DataGridViews は、含まれているコントロールのほとんどのイベントを公開しません。代わりに、これらのコントロールがフックされ、DGV が処理可能な独自のイベントを発生させます。CellValueChanged イベントおよび/または CellDirtyStatusChanged イベントを見てください。最初のものは、ユーザーがセルの値を変更し、そのセルがフォーカスを失ったときに発生します。CellDirtyStatusChanged は、セルの値が最初に変更されるとすぐに、コミットが実際に発生する前に発生します。