C# DockPanelSuite を使った Docking Window アプリの作り方(レイアウト保存、読み込み編)

まで終わったら後はレイアウトの保存、読み込み機能を追加してみよう。

DockPanel.SaveAsXml()
DockPanel.LoadFromXml()

を使用して、起動時に読み込み、終了時に保存を行うように変更する。
保存ファイルのパスは実行ファイルのフルパスの拡張子「exe」を「layout.xml」に変えたものになる。

Form1 のソースを編集

using WeifenLuo.WinFormsUI.Docking;
using System.Diagnostics;

public partial class Form1 : Form
{
    // dockPanel1 で管理するフォーム達
    private Form2 form2 = null;
    private Form3 form3 = null;
    private Form4 form4 = null;

    #region dock layout

    // 実行ファイルのフルパスの .exe を .layout.xml に変えたパスを取得
    private string LayoutFilePath
    {
        get
        {
            string exePath = Process.GetCurrentProcess().MainModule.FileName;
            return System.IO.Path.ChangeExtension(exePath, "layout.xml");
        }
    }

    // レイアウト読み込み
    private void LayoutLoad()
    {
        try
        {
            DeserializeDockContent deserializeDockContent 
                = new DeserializeDockContent(GetDockContent);
            dockPanel1.LoadFromXml(LayoutFilePath, deserializeDockContent);
        }
        catch(Exception ee)
        {
            // 初回起動など保存ファイルがない場合などならレイアウト無視で全部表示開始
            form2.Show(dockPanel1);
            form3.Show(dockPanel1);
            form4.Show(dockPanel1);
        }
    }

    // レイアウト保存
    private void LayoutSave()
    {
        dockPanel1.SaveAsXml(LayoutFilePath);
    }

    // レイアウト読み込み時の保存名からどのフォームかを判定する処理
    private IDockContent GetDockContent(string persistString)
    {
        // フォームのクラス名で保存されているのでそれから判定してあげる
        if(persistString.Equals(typeof(Form2).ToString()))
        {
            return form2;
        }
        else if(persistString.Equals(typeof(Form3).ToString()))
        {
            return form3;
        }
        else if(persistString.Equals(typeof(Form4).ToString()))
        {
            return form4;
        }
        return null;
    }

    #endregion


    public Form1()
    {
        InitializeComponent();

        // フォーム達を生成しておく
        form2 = new Form2();
        form2.Text = "Form2";
        form2.HideOnClose = true; // 閉じられた時に非表示にするだけ

        form3 = new Form3();
        form3.Text = "Form3";
        form3.HideOnClose = true; // 閉じられた時に非表示にするだけ

        form4 = new Form4();
        form4.Text = "Form4";
        form4.HideOnClose = true; // 閉じられた時に非表示にするだけ

        LayoutLoad(); // レイアウト読み込み
    }

    private void Form1_FormClosed(object sender, FormClosedEventArgs e)
    {
        LayoutSave(); // レイアウト保存

        // 掃除
        form2?.Dispose();
        form3?.Dispose();
        form4?.Dispose();
    }

    private void windowToolStripMenuItem_DropDownOpening(object sender, EventArgs e)
    {
        // メニューが開かれる直前:見えなくなっているフォームのメニューだけ有効化する
        form2ToolStripMenuItem.Text = form2.IsHidden ? "Form2 を表示" : "Form2 を消す";
        form3ToolStripMenuItem.Text = form3.IsHidden ? "Form3 を表示" : "Form3 を消す";
        form4ToolStripMenuItem.Text = form4.IsHidden ? "Form4 を表示" : "Form4 を消す";
    }

    private void form2ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        if(form2.IsHidden) { form2.Show(); } else { form2.Hide(); } // Form2 の再表、非表示切り替え
    }

    private void form3ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        if(form3.IsHidden) { form3.Show(); } else { form3.Hide(); } // Form2 の再表、非表示切り替え
    }

    private void form4ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        if(form4.IsHidden) { form4.Show(); } else { form4.Hide(); } // Form2 の再表、非表示切り替え
    }
}

これで終了時のレイアウトが保存され、次の起動時に読み込まれるようになる。

DockPanelSuite-form-layout-save-load

問題点

まだ次のような問題点がある。

  1. 保存、読み込みされるレイアウトは DockPanel 管理の物だけで、メインフォーム(Form1)の位置、サイズは含まれない。
  2. 同じFormクラスを複数個表示させる場合には対応できていない。

1については、Form1 の Bounds プロパティを同様に保存、読み込みすれば良いだけなので説明はしない。
というわけで、同じFormクラスを複数個 DockPanel で管理しないならここまでで十分かなと。

2については。。。次回へ続く。 続いた。