首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C# DataGridView 切換資料源時資料消失?BindingSource 與刷新機制詳解

     編輯:程式設計綜合問答

在同一視窗放置兩個 `DataGridView`,分別綁定不同資料庫視圖,點擊「刷新」顯示 A、點擊「查看」顯示 B,結果切換時資料消失。核心原因通常是:**直接對 `DataGridView.DataSource` 重新賦值而未正確處理 `BindingContext`、或兩個 Grid 共用同一 `BindingSource` 導致位置同步混亂**。以下提供標準解決模式。

錯誤示範

// ❌ 直接重設 DataSource,且未考慮 BindingContext
private void btnRefresh_Click(object sender, EventArgs e) {
    grid1.DataSource = GetViewA(); // grid1 顯示 A
}

private void btnView_Click(object sender, EventArgs e) {
    grid2.DataSource = GetViewB(); // grid2 顯示 B,但 grid1 資料消失?
}

正確模式:各自獨立 BindingSource


public partial class MainForm : Form {
    // 兩個獨立的 BindingSource,互不干擾
    private readonly BindingSource bsGrid1 = new BindingSource();
    private readonly BindingSource bsGrid2 = new BindingSource();

    public MainForm() {
        InitializeComponent();

        // 設計時或載入時綁定
        grid1.DataSource = bsGrid1;
        grid2.DataSource = bsGrid2;

        // 可選:設定 AutoGenerateColumns = false,手動定義 Columns
    }

    private void btnRefresh_Click(object sender, EventArgs e) {
        var dt = GetViewA(); // 返回 DataTable 或 List<T>
        bsGrid1.DataSource = dt; // 只更新 BindingSource
        // grid1 會自動重繪,grid2 完全不受影響
    }

    private void btnView_Click(object sender, EventArgs e) {
        var dt = GetViewB();
        bsGrid2.DataSource = dt;
    }

    // 範例資料取得
    private DataTable GetViewA() { /* ... */ return new DataTable(); }
    private DataTable GetViewB() { /* ... */ return new DataTable(); }
}

關鍵原理:BindingContext 隔離

  • 每個 `Control` 有自己的 `BindingContext`(若未指定則繼承父容器)。
  • 當兩個 `DataGridView` 共用同一 `BindingContext` 且綁定同一資料源類型時,貨幣管理器會同步「當前位置」,導致切換資料源時位置錯亂、顯示空白。
  • 使用**獨立 `BindingSource`** 相當於給每個 Grid 獨立的貨幣管理器,徹底隔離狀態。

進階:若必須共用同一 DataTable 但不同檢視


// 共用 DataTable,但用不同 DataView 過濾/排序
var dv1 = new DataView(sharedTable) { RowFilter = "Type='A'" };
var dv2 = new DataView(sharedTable) { RowFilter = "Type='B'" };
bsGrid1.DataSource = dv1;
bsGrid2.DataSource = dv2;

常見坑點檢查清單

現象原因修正
切換後 Grid 顯示空白行`DataSource` 設為 `null` 再設新值,導致 Columns 清除改用 `BindingSource.DataSource = newData` 保留 Columns
兩個 Grid 同步捲動/選取共用同一 `BindingSource` 或 `BindingContext`各自 `new BindingSource()`
資料更新但介面不刷新`DataTable` 變更未觸發 `ListChanged`確認 `BindingSource` 綁定的是 `DataTable`/`BindingList` 而非陣列
例外:`Operation is not valid because it results in a reentrant call`在 `ListChanged` 事件中修改同一 `BindingSource`用 `BeginInvoke` 延遲執行或改用獨立資料源

除錯技巧


// 即時檢查綁定狀態
private void DumpBindingInfo(DataGridView grid, string name) {
    Console.WriteLine($"{name}: DataSource={grid.DataSource?.GetType().Name}, " +
                      $"BindingContext={grid.BindingContext?.GetHashCode()}, " +
                      $"Rows={grid.Rows.Count}");
}

// 在按鈕點擊前後呼叫
DumpBindingInfo(grid1, "Grid1");
DumpBindingInfo(grid2, "Grid2");

核心原則:**每個 DataGridView 專屬一個 BindingSource**,資料切換只更新 BindingSource.DataSource,即可避免資料消失、同步干擾等疑難雜症。


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved