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

C# WinForm 多窗體共享 List 數據:構造函數注入實例引用

     編輯:程式設計疑難解答

問題場景

Form1 有一個 List<T> dataList,已填充數據。需在 Form2、Form3 中**讀取/修改同一個列表實例**。若在 Form2 中 new List<T>() 會創建新列表,導致數據不同步。

核心方案:構造函數傳遞引用 (推薦、類型安全、解耦)

// Form1.cs
public partial class Form1 : Form {
    private List<UserData> sharedList = new List<UserData>();

    private void btnOpenForm2_Click(object sender, EventArgs e) {
        // 關鍵:將共享列表實例傳給 Form2 構造函數
        Form2 form2 = new Form2(sharedList); 
        form2.Show();
    }
    
    private void btnOpenForm3_Click(object sender, EventArgs e) {
        Form3 form3 = new Form3(sharedList); // 同一實例傳給 Form3
        form3.Show();
    }
}

// Form2.cs
public partial class Form2 : Form {
    private readonly List<UserData> _sharedList; // 只讀字段,持有引用
    
    // 構造函數接收列表引用
    public Form2(List<UserData> sharedList) {
        InitializeComponent();
        _sharedList = sharedList; // 保存引用,不 new 新列表
    }
    
    private void Form2_Load(object sender, EventArgs e) {
        // 直接使用 _sharedList,讀取/修改即同步到 Form1 和 Form3
        dataGridView1.DataSource = _sharedList; 
    }
    
    private void btnAdd_Click(object sender, EventArgs e) {
        _sharedList.Add(new UserData { Name = "New" }); // 修改同步生效
        dataGridView1.Refresh();
    }
}

// Form3.cs 同理,構造函數接收 List<UserData> sharedList

進階:封裝共享數據上下文 (適用於複雜場景)

// 共享數據容器 (單例或依賴注入)
public class SharedDataContext {
    public List<UserData> UserList { get; } = new List<UserData>();
    public Dictionary<string, Config> Configs { get; } = new Dictionary<string, Config>();
    // 事件通知數據變更
    public event Action DataChanged; 
    public void NotifyChanged() => DataChanged?.Invoke();
}

// Form1 持有上下文實例 (或從 IoC 容器獲取)
private readonly SharedDataContext _ctx = new SharedDataContext();

// 打開子窗體傳遞上下文
Form2 f2 = new Form2(_ctx);
Form3 f3 = new Form3(_ctx);

// 子窗體訂閱變更事件實時刷新 UI
public Form2(SharedDataContext ctx) {
    InitializeComponent();
    _ctx = ctx;
    _ctx.DataChanged += OnDataChanged; // 訂閱
    LoadData();
}
private void OnDataChanged() => this.Invoke(() => LoadData());
private void Form2_FormClosed(...) => _ctx.DataChanged -= OnDataChanged; // 取消訂閱防洩漏

對比:其他方案及優劣

方案優點缺點適用場景
構造函數注入 (推薦)顯式依賴、類型安全、易測試、無單例污染需修改構造函數簽名多數 WinForm 多窗體共享場景
靜態類/單例持有 List全局隨處訪問強耦合、難測試、生命週期不可控、多線程不安全極簡單工具類,非業務核心數據
Application.OpenForms 遍歷查找 Form1 取屬性無需修改構造函數極度脆弱、依賴 Form 名稱/類型、運行時易出錯不推薦
文件/數據庫中轉持久化、跨進程性能差、同步複雜、過度設計需持久化/跨進程共享時

關鍵原則

  1. 共享即引用同一對象: 傳遞引用 (構造函數/屬性/方法參數),**絕不 new 新集合**。
  2. 所有權清晰: Form1 (或上下文) 擁有列表實例,子窗體僅持有引用使用。
  3. 線程安全: 若多線程訪問,用 lock(_sharedList) 或 ConcurrentBag / BindingList (UI綁定友好)。
  4. 事件通知更新: 共享數據變更時觸發事件,子窗體訂閱刷新 UI,保持數據一致性視覺化。

總結

C# WinForm 多窗體共享 List,核心是「構造函數注入共享實例引用」。 Form1 持有列表實例,創建 Form2/3 時通過構造函數傳入。子窗體保存引用直接操作,修改即時同步。進階場景可封裝 SharedDataContext 統一管理多數據源並提供變更通知事件。拒絕靜態單例、拒絕 Application.OpenForms 硬查找。

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