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

DataGridView CellEnter事件首次加载RowCount显示异常问题

Fix Incorrect RowCount in DataGridView CellEnter Event on First Load

I've run into similar timing issues with DataGridView's event sequence when working with dynamic control creation and data binding, so let's break down what's happening and how to fix it.

What's Causing the Problem?

The root issue is event timing during initial data binding: when your user control first loads, the CellEnter event fires before the DataGridView finishes loading all rows from the DataSource. At this point, the control only has the default "new row" (since AllowUserToAddRow = True) plus a temporary empty row, hence the incorrect RowCount = 2. Later events like DataSourceChanged fire after the data is fully loaded, so they get the correct count.

Your workaround of destroying/re-creating the control exacerbates this because the initial CellEnter trigger happens even faster before the data binding completes fully.

Solutions to Fix the RowCount Display

1. Delay RowCount Fetch with BeginInvoke in CellEnter

The simplest fix is to use BeginInvoke to defer the label update until the UI thread has finished processing all pending data binding tasks. This ensures the DataGridView has fully loaded all rows before you check RowCount.

Modify your CellEnter event handler like this:

private void DataGridView_CellEnter(object sender, DataGridViewCellEventArgs e)
{
    var dgv = sender as DataGridView;
    if (dgv == null || e.RowIndex < 0) return;

    // Defer the update to after UI thread finishes data loading
    BeginInvoke(new Action(() =>
    {
        // Calculate actual data rows (exclude the "new row" if enabled)
        int actualRowCount = dgv.RowCount - (dgv.AllowUserToAddRow ? 1 : 0);
        int currentRowNumber = e.RowIndex + 1;

        // Handle the "new row" case
        if (e.RowIndex == dgv.NewRowIndex)
        {
            currentRowNumber = actualRowCount + 1;
        }

        // Update your label
        rowCountLabel.Text = $"{currentRowNumber} of {actualRowCount}";
    }));
}

2. Combine DataSourceChanged and CellEnter for Full Coverage

To handle both initial load and data updates (like row adds/deletes), add a DataSourceChanged handler to sync the label when the data source changes, and keep the modified CellEnter handler for row selection changes:

private void DataGridView_DataSourceChanged(object sender, EventArgs e)
{
    var dgv = sender as DataGridView;
    if (dgv == null) return;

    UpdateRowCountLabel(dgv);
}

// Helper method to reuse label update logic
private void UpdateRowCountLabel(DataGridView dgv)
{
    int actualRowCount = dgv.RowCount - (dgv.AllowUserToAddRow ? 1 : 0);
    int currentRowNumber = 0;

    if (dgv.CurrentRow != null)
    {
        currentRowNumber = dgv.CurrentRow.Index + 1;
        if (dgv.CurrentRow.Index == dgv.NewRowIndex)
        {
            currentRowNumber = actualRowCount + 1;
        }
    }

    rowCountLabel.Text = $"{currentRowNumber} of {actualRowCount}";
}

Then call this helper method in your CellEnter handler (inside the BeginInvoke block) instead of duplicating code.

3. Manual Label Update After Control Re-Creation

Since you're destroying and re-adding the control to fix column residue, add a manual label update right after binding the data source. This ensures the label shows the correct count immediately without waiting for CellEnter:

In your form's button click handler:

private void TabSimulatorButton_Click(object sender, EventArgs e)
{
    // Clean up old control
    if (_currentDataControl != null)
    {
        Controls.Remove(_currentDataControl);
        _currentDataControl.Dispose();
    }

    // Create and configure new control
    var newDataControl = new YourDataGridViewUserControl();
    newDataControl.DataGridView.DataSource = GetYourDataSource(); // Your data fetch logic

    // Manually update the label immediately after binding
    newDataControl.UpdateRowCountLabel();

    // Add to form
    Controls.Add(newDataControl);
    _currentDataControl = newDataControl;
}

Add the public UpdateRowCountLabel method to your user control:

public void UpdateRowCountLabel()
{
    UpdateRowCountLabel(DataGridView);
}

Why These Fixes Work

  • BeginInvoke ensures we wait until the DataGridView has finished rendering all rows before checking RowCount, avoiding the premature CellEnter trigger issue.
  • Combining DataSourceChanged and CellEnter covers both initial data load and user-driven row selection changes, plus handles row adds/deletes correctly.
  • Manual update after control re-creation skips the unreliable initial CellEnter trigger and sets the label correctly right away.

This should resolve the inconsistent RowCount display in your CellEnter event, even for the problematic tables on first load.

内容的提问来源于stack exchange,提问作者CT19X

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:46:06