需求:用戶編輯單元格結束時驗證數據,不合法則取消編輯、保持原值、提示錯誤。CellEndEdit 無 Cancel 屬性,無法直接阻止提交。
private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) {
// 1. 僅驗證特定列
if (e.ColumnIndex != targetColumnIndex) return;
// 2. 獲取用戶輸入值
string input = e.FormattedValue?.ToString()?.Trim();
// 3. 業務驗證邏輯
if (!IsValid(input)) {
// 4. 關鍵:取消編輯
e.Cancel = true;
// 5. 用戶提示(非模態,避免阻塞 UI 線程)
this.BeginInvoke((Action)(() => {
MessageBox.Show("輸入格式不正確,請重新輸入", "驗證失敗",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
}));
}
}
e.Cancel = true:通知 DataGridView 取消本次編輯,單元格恢復原值,焦點保留在該單元格。e.FormattedValue:獲取用戶當前編輯控件中的顯示文本,而非底層數據源值。BeginInvoke:彈窗必須異步執行,否則會干擾編輯控件的焦點狀態導致異常。若需跨列聯動驗證(如開始時間 < 結束時間),使用 RowValidating 同樣設置 e.Cancel = true。
CellValidating 中直接修改 dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value 無效,因數據源尚未更新。DataGridView.DataSource 綁定 BindingList,驗證失敗後實體對象屬性不會被修改,安全。VirtualMode = true) 下需在 CellValuePushed 中驗證並拋異常回滾。public static class DataGridViewExtensions {
public static void AddCellValidation(this DataGridView dgv, int colIndex, Func validator, string errorMsg) {
dgv.CellValidating += (s, e) => {
if (e.ColumnIndex == colIndex && !validator(e.FormattedValue?.ToString())) {
e.Cancel = true;
dgv.BeginInvoke((Action)(() => MessageBox.Show(errorMsg)));
}
};
}
}
// 使用
dataGridView1.AddCellValidation(2, v => decimal.TryParse(v, out _), "請輸入有效金額");