You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:

  1. CellValueChanged: Handles immediate changes to individual cells
  2. CellEndEdit: Ensures validation runs after the user finishes editing a cell (avoids triggering mid-edit)
  3. KeyDown: Catches bulk paste operations (Ctrl+V)
  4. 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 TryParse to 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 IsNewRow to 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:26:29