C#非绑定DataGridView列值校验:列总和需为100或空
Hey, I get exactly what you're dealing with here—using CellValueChanged works fine when you fill cells row by row, but it falls flat when you edit columns in bulk or modify cells randomly because that event only fires when a single cell's value changes. Let's fix this with a more robust approach:
Step 1: Extract Column Validation Logic into Reusable Methods
First, let's pull the total-checking and style-setting code into standalone methods so we can call them from multiple places. This keeps things clean and avoids duplicate code.
Here's a sample implementation (I'll use decimal for numeric values—adjust to int/float if your use case needs it):
private void ValidateSingleColumn(int columnIndex) { // Skip invalid column indices or the new row placeholder if (columnIndex < 0 || columnIndex >= dataGridView1.Columns.Count) return; DataGridViewColumn targetCol = dataGridView1.Columns[columnIndex]; decimal columnTotal = 0; bool hasEmptyOrInvalidCell = false; // Calculate column total and check for empty/invalid cells foreach (DataGridViewRow row in dataGridView1.Rows) { if (row.IsNewRow) continue; DataGridViewCell cell = row.Cells[columnIndex]; if (cell.Value == null || string.IsNullOrWhiteSpace(cell.Value.ToString())) { hasEmptyOrInvalidCell = true; break; // No need to calculate further if there's an empty cell } // Safely parse cell value to a number if (!decimal.TryParse(cell.Value.ToString(), out decimal cellValue)) { hasEmptyOrInvalidCell = true; break; } columnTotal += cellValue; } // Update column style based on validation results if (hasEmptyOrInvalidCell) { // Reset to default style if there's an empty/invalid cell targetCol.DefaultCellStyle = dataGridView1.DefaultCellStyle; } else if (columnTotal > 100) { // Set error style for columns exceeding 100 var errorStyle = new DataGridViewCellStyle(dataGridView1.DefaultCellStyle); errorStyle.BorderWidth = 2; errorStyle.ForeColor = Color.Red; errorStyle.BackColor = Color.LightPink; // Optional: Background highlight for better visibility targetCol.DefaultCellStyle = errorStyle; } else if (columnTotal == 100) { // Reset to default if total is exactly 100 targetCol.DefaultCellStyle = dataGridView1.DefaultCellStyle; } } // Optional: Validate all columns at once (great for initial load or bulk edits) private void ValidateAllColumns() { for (int i = 0; i < dataGridView1.Columns.Count; i++) { ValidateSingleColumn(i); } }
Step 2: Hook Up Validation to Multiple Events
To cover every editing scenario—single cell changes, bulk pastes, column-wise edits—call the validation methods from these key events:
CellValueChanged: Handles immediate changes to individual cellsCellEndEdit: Ensures validation runs after the user finishes editing a cell (avoids triggering mid-edit)KeyDown: Catches bulk paste operations (Ctrl+V)- Manual Calls: If you modify cells via code, call the validation method right after the update
Here's how to wire up these events:
private void DataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e) { // Validate only the modified column for better performance if (e.RowIndex >= 0 && e.ColumnIndex >= 0) { ValidateSingleColumn(e.ColumnIndex); } } private void DataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e) { // Re-validate after editing completes if (e.ColumnIndex >= 0) { ValidateSingleColumn(e.ColumnIndex); } } private void DataGridView1_KeyDown(object sender, KeyEventArgs e) { // Handle Ctrl+V paste operations if (e.Control && e.KeyCode == Keys.V) { // Add a small delay to ensure paste finishes before validating Task.Delay(100).ContinueWith(_ => { // Use Invoke to run validation on the UI thread this.Invoke((Action)ValidateAllColumns); }); } }
Key Tips for Smooth Operation
- Safe Numeric Parsing: Always use
TryParseto avoid crashes if users enter non-numeric values. - Performance: Validating only the modified column (instead of all columns) is way faster, especially with large datasets.
- New Row Handling: Skip
IsNewRowto ignore the empty placeholder row at the bottom of the DataGridView. - Style Flexibility: Adjust the error style (border color, background color) to match your app's design system.
This approach ensures that no matter how the user edits the DataGridView—row by row, column by column, or via bulk paste—the column totals are always validated, and the red border appears correctly when totals exceed 100.
内容的提问来源于stack exchange,提问作者Chelsea WANG

