首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# WinForms MDI 父子視窗架構完整入門教學

     編輯:關於C#

MDI 核心概念

  • MDI 父視窗 (MDI Container):`IsMdiContainer = true`,提供工作區、選單、工具列。
  • MDI 子視窗:`MdiParent = 父視窗`,活動於父視窗用戶區內,可最大化、最小化、平鋪、層疊。

建立步驟 (VS 設計師 + 程式碼)

  1. 新增 **Form** → 命名 `MdiMain` → 屬性 `IsMdiContainer = true`。
  2. 新增 **Form** → 命名 `MdiChild` (可設計為通用編輯器、報表檢視等)。
  3. 在 `MdiMain` 加入 `MenuStrip`,建立選單項「新增視窗」。
  4. 雙擊選單項產生 `Click` 事件,撰寫開啟子視窗程式碼。

核心程式碼


public partial class MdiMain : Form
{
    private int _childCount = 0;

    public MdiMain() => InitializeComponent();

    private void mnuNewWindow_Click(object sender, EventArgs e)
    {
        _childCount++;
        var child = new MdiChild
        {
            MdiParent = this,
            Text = $"子視窗 {_childCount}"
        };
        child.Show(); // 非模態顯示
    }

    // 選單:平鋪/層疊/最小化所有
    private void mnuTileHorizontal_Click(object sender, EventArgs e) => LayoutMdi(MdiLayout.TileHorizontal);
    private void mnuTileVertical_Click(object sender, EventArgs e) => LayoutMdi(MdiLayout.TileVertical);
    private void mnuCascade_Click(object sender, EventArgs e) => LayoutMdi(MdiLayout.Cascade);
    private void mnuArrangeIcons_Click(object sender, EventArgs e) => LayoutMdi(MdiLayout.ArrangeIcons);
}

防止重複開啟同類型子視窗 (單例模式)


private void mnuOpenReport_Click(object sender, EventArgs e)
{
    // 檢查是否已開啟同類型
    var existing = MdiChildren.FirstOrDefault(f => f.GetType() == typeof(ReportForm));
    if (existing != null)
    {
        existing.Activate(); // 置頂聚焦
        return;
    }

    var report = new ReportForm { MdiParent = this };
    report.FormClosed += (s, e) => { /* 可清理資源 */ };
    report.Show();
}

子視窗關閉與資源釋放


public partial class MdiChild : Form
{
    public MdiChild() => InitializeComponent();

    private void btnClose_Click(object sender, EventArgs e) => Close();

    protected override void OnFormClosed(FormClosedEventArgs e)
    {
        // 釋放非託管資源、取消訂閱事件等
        base.OnFormClosed(e);
    }
}

進階技巧

需求解決方案
子視窗狀態持久化覆寫 `OnClosing` 儲存 `Location`/`Size`/`WindowState` 至設定檔
父視窗選單動態合併子視窗 `MenuStrip` 設定 `MergeAction` / `MergeIndex`,父視窗自動合併
工具列共用父視窗 `ToolStrip` 可被子視窗透過 `MdiParent.Controls` 存取
跨子視窗通訊父視窗做中介者 (Mediator) 或使用事件總線
自訂標籤頁式 MDI使用第三方套件 (DockPanel Suite, DevExpress, Telerik) 或自繪 `TabControl` 宿主

常見問題排查

  • 子視窗不顯示:確認 `MdiParent` 設在 `Show()` 前,且父視窗 `IsMdiContainer = true`。
  • 背景圖片不顯示:MDI 用戶區為 `MdiClient` 控制項,需自行繪製或設定 `BackgroundImage` 於 `MdiClient`。
  • 最大化子視窗選單合併異常:檢查 `MenuStrip` 項目 `MergeAction` 設定 (`MatchOnly`/`Insert`/`Remove`)。

現代替代方案

傳統 MDI 在高 DPI、觸控、跨平台支援較弱。新專案建議考慮:

  • Tabbed Document Interface (TDI):單視窗 + `TabControl`/`TabPage` 宿主 `UserControl`。
  • Docking Library:DockPanel Suite (開源)、DevExpress Docking、AvalonDock (WPF)。
  • WPF / MAUI / Blazor:原生支援現代佈局、資料繫結、MVVM。

總結

MDI 是 WinForms 經典多文件介面架構,核心在於 `IsMdiContainer`、`MdiParent`、`LayoutMdi` 三大支柱。掌握單例開啟、選單合併、狀態持久化等實務技巧,即可快速建構傳統桌面企業應用。新專案請評估現代替代方案以獲得更佳使用者體驗。

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