DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

.NETでDocking Windowを使う

Visual Studioのメインウィンドウの上下左右には、ツールボックス、ソリューションエクスプローラ、プロパティウィンドウなどがくっついており、これらはドラッグすることにより、分離させてウィンドウにしたり、別の位置にドッキングさせたり、サイズを変えたりすることが出来るようになっています。このようなウィンドウをDocking Windowと呼びます。ここでは、.NETでDocking Windowを可能にするライブラリを紹介します。なお、ここでは無料で使用できるものしか紹介しません。

もし、ここで紹介されてないけれど、優れたライブラリがあるという場合は、ぜひご連絡ください。よろしくお願いいたします。

DockPanel Suite

現在最も一般的なライブラリは、DockPanel Suiteであるようです。現在のバージョンは2.9.0で、ライセンスはMITです。

DockPanel Suite

Docking Windowとしての機能は一通りそろえており、「自動的に隠す」機能(右上のピンのマークをクリックすることにより、Windowが自動的に隠れ、マウスを持っていくことにより、再び表示できる機能)や、タブとしてドッキングさせる機能、Docking Windowの状態を保存、復元する機能などがあります。

DockPanel Suiteでは、Docking WindowとなるDockContentクラスがSystem.Windows.Forms.Formクラスを継承しているため、Docking Windowのデザインをフォームデザイナで行えます。

DockPanel Suiteをちょっと使ってみましょう。まず、「ツールボックス」を開き、適当な個所を右クリックしてコンテキストメニューを表示し、「アイテムの選択」を選択します。「ツールボックスアイテムの選択」ダイアログで「参照」ボタンを押して、「WeifenLuo.WinFormsUI.Docking.dll」を選択します。「OK」ボタンを押して「ツールボックスアイテムの選択」ダイアログを閉じると、ツールボックスに「DockPanel」が追加されます。

このDockPanelをフォームに貼り付け、DockプロパティをFillにしておきます(しなくても結構です)。このDockPanelの部分にDocking Windowがドッキングされます。

次にDocking Windowを作成します。まず、メニューの「プロジェクト」-「新しい項目の追加」を選択して「新しい項目の追加」ダイアログを表示します。ここで「継承されたフォーム」を選択し、「追加」をクリックします。「継承ピッカー」の「参照」をクリックし、「WeifenLuo.WinFormsUI.dll」を選択します。「継承元コンポーネントの指定」で「DockContent」を選択し、「OK」ボタンを押します。これで作成されるフォームがDocking Windowとなりますので、フォームデザイナで適当にデザインしましょう。

作成したDocking Windowを表示させるには、Showメソッドを使用します。次の例では、DockPanelである「dockPanel1」に、Docking Windowである「Form2」を左端にドッキングされた状態で表示させています。このコードは、dockPanel1のあるフォームに記述されているものとします。

VB.NET
コードを隠すコードを選択
'dockPanel1のあるフォームをMDIコンテナとする
Me.IsMdiContainer = True
'IsMdiContainerをTrueにしない場合は、DocumentStyleをDockingWindowにする
dockPanel1.DocumentStyle = _
    WeifenLuo.WinFormsUI.Docking.DocumentStyle.DockingWindow

'Docking Windowを作成する
Dim f2 As New Form2()
'dockManager1の左端にドッキングさせて表示する
f2.Show(dockPanel1, WeifenLuo.WinFormsUI.Docking.DockState.DockLeft)
C#
コードを隠すコードを選択
//dockPanel1のあるフォームをMDIコンテナとする
this.IsMdiContainer = true;
//IsMdiContainerをTrueにしない場合は、DocumentStyleをDockingWindowにする
//dockPanel1.DocumentStyle =
//    WeifenLuo.WinFormsUI.Docking.DocumentStyle.DockingWindow;

//Docking Windowを作成する
Form2 f2 = new Form2();
//dockManager1の左端にドッキングさせて表示する
f2.Show(dockPanel1, WeifenLuo.WinFormsUI.Docking.DockState.DockLeft);

DockManager Control

上記「DockPanel Suite」の基になったのが、「DockManager Control」です。

Magic Docking

以前最も一般的だったライブラリが、「Magic Library」にある「Magic Docking」です。

使い方も簡単です。「MagicLibrary.DLL」をプロジェクトの「参照設定」に追加し、次のようなコードをフォームのLoadイベントハンドラ(またはコンストラクタ)に書くだけで、Docking Windowができてしまいます。

VB.NET
コードを隠すコードを選択
'Imports Crownwood.Magic.Common
'Imports Crownwood.Magic.Docking
'がソースファイルの一番上に書かれているものとする

Private _dockingManager As DockingManager = Nothing

'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load
    'DockingManagerオブジェクトの作成
    _dockingManager = New DockingManager(Me, VisualStyle.IDE)
    'Contentとして新しく作成したRichTextBoxコントロールを追加
    _dockingManager.Contents.Add(New RichTextBox, "RichTextBox")
    'Contentを表示
    _dockingManager.ShowContent( _
        _dockingManager.Contents("RichTextBox"))
End Sub
C#
コードを隠すコードを選択
//using Crownwood.Magic.Common;
//using Crownwood.Magic.Docking;
//がソースファイルの一番上に書かれているものとする

private DockingManager _dockingManager = null;

//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, System.EventArgs e)
{
    //DockingManagerオブジェクトの作成
    _dockingManager = new DockingManager(this, VisualStyle.IDE);
    //Contentとして新しく作成したRichTextBoxコントロールを追加
    _dockingManager.Contents.Add(new RichTextBox(), "RichTextBox");
    //Contentを表示
    _dockingManager.ShowContent(
        _dockingManager.Contents["RichTextBox"]);
}

現在は、残念ながらMagic Libraryは有料化され、「DotNetMagic」となりました。バージョン1.7.4までのMagic Libraryは今まで通り無料で使用できるようです。

バージョン1.7.4は現在単独ではダウンロードすることができないようです。バージョン1.7.4の「MagicLibrary.DLL」は、後述する「DockingManagerExtender」の「executables framework 1.1」に含まれているようです(コメントにてご報告をいただきました)。また、SharpDevelopにも含まれているようです。

The Code Project - Magic Docking」からは、バージョン1.7.0がダウンロードできるようです。

DockingManagerExtender

このようにMagic Dockingの使用は決して難しいものではありませんが、Visual Studioのフォームデザイナを使って設定できるようになればもっと便利になるかもしれません。それを可能にするのが、「DockingManagerExtender」です。これを使えば、コードを自分で一行も書く必要がなくなります。

使い方は、「MagicLibrary.DLL」が「参照設定」に追加された状態で、「ツールボックス」の「コンポーネント」に「DockingManagerExtender.DLL」を追加し、これをフォームに貼り付けるだけです。フォームに貼り付けたDockingManagerExtenderのContainerControlプロパティを適当に設定し(通常は貼り付けたフォームとなるでしょう)、Docking Windowとするコントロールの「DockingManagerExtenderのADockingEnable」プロパティをTrueとすれば、Docking Windowが出来上がります。

SDock

SDockは、CodePlexで公開されているオープンソース(CPL)のライブラリです。現在のバージョンは 1.0.0.1 Alphaで、まだアルファ版ですが、残念ながら8年以上更新されていません。

SDockでは、ドッキングウィンドウの配置をVisual Studioのデザイナだけで行うことができます。以下にその簡単な手順を示します。

  1. Visual Studioの「ツールボックス」に「yukilib.dll」を追加する。
  2. フォームに「SDockBay」を配置する。
  3. 配置したSDockBayの内部をクリックしてMainPaneを選択し、Visual Studioのプロパティウィンドウから、「新規Paneを右にドッキング」を選択する。SDockPaneが右側に追加される。
  4. SDockPaneに好きなコントロールを配置する。プロパティウィンドウの「タブの追加」により、タブを追加することもできる。タブもドッキングウィンドウとして動作する。
  5. 3〜4を繰り返して、Paneやタブを必要なだけ追加する。
  6. 以上。

なおVisual Studioのドッキングウィンドウを例に取れば、SDockBayのMainPaneがコードやフォームデザイナなどが表示される真ん中の部分で、追加したPaneが「ソリューションエクスプローラ」や「プロパティウィンドウ」の部分(タブになっていない時)に当たると考えてよいでしょう。

私が少し試したところでは、不安定な部分が多く、実用には厳しいかもしれません。

SDockに関する質問と回答

上記で「不安定な部分」と表現した事柄に関して、開発者であるyukichikaさんにお知らせしたところ、対処法を含むご回答をいただきましたので、以下に紹介させていただきます。このやり取りは、バージョン 1.0.0.0 Alpha 時のものです。回答の部分は、yukichikaさんからいただいたご回答をほぼそのまま掲載させていただきました。

質問1

  • Visual StudioのフォームデザイナでPaneのサイズを変更すると、境界線が広かったようになります。
  • 次のような手順でアプリケーションを作成すると、おかしくなります。
    1. フォームにSDockBayを配置する。
    2. DockプロパティをFillにする。
    3. 「新規Paneを上にドッキング」を選択してPaneを追加する。
    4. ビルドして実行する。
    5. 実行したアプリケーションで、Paneを下にドッキングさせようとすると、おかしくなる。
  • SDockBayにPane等を配置後、SDockBayのDockを変更すると、Paneが消えます。

質問1に対する回答

  • 【原因】
    上記デザイン時プロパティが正しくシリアル化・逆シリアル化されていない。もしくは「Controlsプロパティで直接追加した」というフラグが正しく動作していない。そのため、OnLayout時の動作が正しく機能しない。
  • 【応急処置方法】
    SDockBayにPaneを追加した後、サイズ変更(Pane,Bayに関わらず)をデザイナ上で行う場合、
    • サイズ変更を行う前に、ビルドを実行する。
    • サイズ変更を行う前に、一度デザイナを閉じ、再度デザイナを開く。
    ことにより、サイズ変更(Dockプロパティでのサイズ変更も含まれます。)に伴うバグは発生しなくなると思います。
    まことに申し訳有りませんが、現状ではユーザ負担の大きい対処法しかありません。 今後のアップデートできちんと対策致します。

質問2

  • SDockBayを削除しても、SDockBayに配置されたコントロールがなくなりません。

質問2に対する回答

  • 【原因】
    • デザイナクラスではIComponentChangeServiceを利用してアンドゥリドゥ管理しています。この利用タイミングが誤っているため。
    • SDockBayのデザイナクラスのAssociatedComponentsプロパティを適切にoverrideしていないため。
  • 【対策法】
    こちらに関しては動作確認後、近日中にアップデートいたします。
  • 履歴:
  • 2007/1/10 「DockPanel Suite」を追加。
  • 2007/4/9 「SDock」を追加。
  • 2008/9/11 「Docking Control」をリンク切れのために削除。
  • 2016/6/1 「DockPanel Suite」を先頭にし、使用例を追加。「それ以外のコントロール」を削除。説明を簡略化など。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • 「???を参照に追加します」の意味が分からないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。