ドッキングする側のウィンドウ DockContentの作成

ドッキング ウィンドウは、DockContentを継承したフォームとして作成します。なおこのクラスは、System.Windows.Forms.Formを継承しています。

DockContentの作成

正規の方法

ソリューション エクスプローラ上でプロジェクトを右クリックし、[追加]の[新しい項目]を選択します。そして[Windows Forms]のカテゴリから[継承されたフォーム]を選択します。

[継承ピッカー]ウィンドウで継承元コンポーネントを指定し、[参照]をクリックします。

「WeifenLuo.WinFormsUI.Docking.dll」ファイルを開きます。

DLLに含まれるコンポーネントから、[DockContent]を指定します。

これで、DockContentを継承したフォームが作成されます。

簡単な方法

  1. ソリューション エクスプローラ上でプロジェクトを右クリックし、[追加]の[Windows フォーム]を選択する。
  2. 作成されたフォームの型を、Formから[WeifenLuo.WinFormsUI.Docking.DockContent]へ変更する。
public partial class MyDockContent : WeifenLuo.WinFormsUI.Docking.DockContent
{
}

既存のコントロールをドッキング可能にする方法

FormやUserControlを継承したコントロールならば、その基本クラスをDockContentに変更するだけです。そうではないならば、そのコントロールを格納するDockContentを作成した上で、そのDockContentをドッキング ウィンドウとして表示します。

private MyControl myControl;
private WeifenLuo.WinFormsUI.Docking.DockContent myControlContainer; // コントロールのコンテナ


myControlContainer = new WeifenLuo.WinFormsUI.Docking.DockContent();
myControlContainer.Controls.Add(myControl); // コンテナにコントロールを追加
myControlContainer.Show(dockPanel);         // コンテナをドッキング可能として表示

DockContentの表示

DockPanelを所有する側からそれをShow()の引数に渡して表示することで、そのDockPanelにドッキングできるようになります。逆にDockPanelを指定せずに表示すると、どこにもドッキングできません。

public partial class Form1 : Form
{
    private WeifenLuo.WinFormsUI.Docking.DockPanel dockPanel;
    private MyDockContent myDockContent;

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        // dockPanelがMDIの子コントロールではないとき、DocumentStyleが既定のDockingMdiのままDockContentを表示すると、InvalidOperationExceptionとして例外が投げられる
        dockPanel.DocumentStyle = DocumentStyle.DockingWindow;

        myDockContent = new MyDockContent();
        myDockContent.Show(dockPanel);
    }
}
メソッド 機能
void Show(DockPanel dockPanel); dockPanelにドッキング可能な状態で、設定済みのDockStateで表示

設定済みのDockStateが"Unknown"または"Hidden"だと、「Invalid DockState: Content can not be showed as "Unknown" or "Hidden".」としてArgumentExceptionが投げられる。よってDockStateを指定した方が安全

テーマが設定されていないと、「DockPanel.Theme must be set to a valid theme.」としてArgumentExceptionが投げられる。

void Show(DockPanel dockPanel, DockState dockState); dockPanelにドッキング可能な状態で、指定のdockStateで表示
void Show(DockPanel dockPanel, Rectangle floatWindowBounds); dockPanelにドッキング可能な状態で、floatWindowBoundsの大きさで、フロートウィンドウとして表示
void Show(DockPane pane, IDockContent beforeContent); pane区画の、beforeContentより前に表示
void Show(DockPane previousPane, DockAlignment alignment, double proportion); previousPane区画のalignmentの位置に、proportionの割合だけずらして表示

複数のDockContentの表示

複数のDockContentを同一のDockPanelに表示した場合、後から表示したものが右または下のタブに表示され、最後のものが最初にアクティブになります。

通常とは逆に、前へ追加するには次のようにします。

dockPanel2.Show(dockPanel1.Pane, dockPanel1);

既存のDockContentと同一の区画へ、位置をずらして追加するには次のようにします。

double proportion = 0.5;
dockPanel2.Show(dockPanel1.Pane, DockAlignment.Bottom, proportion);

指定の区画への追加

追加位置 追加方法
上下左右の同一位置の中の先頭の区画、の末尾
myDockContent.Show(dockPanel, DockState.DockRight);
指定区画、の先頭
myDockContent.Show(dockPanel.Pane, dockPanel);
上記以外、の末尾
myDockContent.Show(dockPanel);
myDockContent.Pane = dockPanel.Pane;

非表示にされたウィンドウの表示

非表示されたウィンドウをプログラムから表示するには、Show()を呼ぶだけです。しかしAutoHideの状態のウィンドウはタブが表示されるだけのため、表示されたことを視認しづらいです。この問題には、親ウィンドウのActiveAutoHideContentに自身を設定することで対処できます。c# - Calling up DockPanel-Suite's "AutoHidden" DockContent programmatically - Stack Overflow

myDockContent.Show();

if (myDockContent.DockState == DockState.DockTopAutoHide
    || myDockContent.DockState == DockState.DockBottomAutoHide
    || myDockContent.DockState == DockState.DockLeftAutoHide
    || myDockContent.DockState == DockState.DockRightAutoHide)
{
    // アクティブなウィンドウとして設定することで、閉じられた状態を展開させる
    myDockContent.DockPanel.ActiveAutoHideContent = myDockContent;

    // 再び閉じられないように、実際にアクティブにする
    myDockContent.Activate();
}

フロート ウィンドウとして表示するときのサイズの指定

引数でDockState.Floatとして表示するとフロート ウィンドウとして表示されますが、

myDockContent.Show(dockPanel, DockState.Float);

そのときのサイズはDockPanelクラスのDefaultFloatWindowSizeプロパティの定義

public Size DefaultFloatWindowSize { get; set; } = new Size(300, 300);

により、300x300に設定されます。これをサイズを指定して表示するにはRectangleを渡して

myDockContent.Show(dockPanel, myDockContent.Bounds);

とします。このオーバーロードは内部でDockState.Floatを引数に取るShow()を呼ぶため、この方法でもフロート ウィンドウとなります。

DockContentの設定

DockContent のプロパティ
プロパティ 内容
bool AllowRedocking trueならば、ドラッグアンドドロップによって再びドッキングすることを許可
double AutoHidePortion AutoHideモードで表示されるときの表示サイズの割合。有効な数値は0.0~1.0の間で、既定値は0.25
bool CloseButton trueならば、[閉じる]ボタンが有効
DockAreas DockableAreas DockAreas ドッキング可能な領域
DockContentHandler DockHandler  
DockPanel DockPanel ドッキング ウィンドウの親
DockState DockState ドッキング状態
DockState ShowHint 初回に表示するときのドッキング位置
bool HideOnClose trueならば、ウィンドウを閉じるように指示されたときに、閉じずに非表示とする
bool IsActivated trueならば、現在アクティブ
bool IsFloat trueならば、フロート ウィンドウ
bool IsHidden trueならば、非表示

これはDockStateプロパティがHiddenであることを意味していて、タブで他のウィンドウに隠れていたり、AutoHideで隠れていてもtrueとはならない

Hide()を呼び出すことは、IsHiddenをtrueとすることと同じ

bool Visible (Controlから継承) 次の状態のときに、false
  • DockStateプロパティがHidden
  • タブで他のウィンドウに隠れている
  • AutoHideにされてから表示されていない。1度表示されると、隠されてもtrueのまま
DockPane FloatPane フロートでの区画
DockPane Pane 現在の区画
DockPane PanelPane ドッキングされる区画
string TabText DockPaneのタブに表示する文字列。これが設定されていない場合は、Textプロパティの値が用いられる
DockState VisibleState 可視でのドッキング状態。非表示にされる前の状態が保持されている

イベント

派生元のFormに対し、追加で実装されているのは下表のイベントのみです。

イベント 発生タイミング
EventHandler DockStateChanged  

SizeChanged

AutoHideで隠されたり表示されたりすることを通知するイベントはありませんが、そのときウィンドウのサイズが変化することからそれを検知できます。隠されるときにはSizeChangedイベントが2度発生します。上端または下端にドッキングしているときは1度目にHeightだけがゼロとなり、2度目にWidthもゼロとなります。左右の端では、1度目にWidthがゼロとなります。

トラブル対処法

不正なスケーリング

フォントを基準とした自動スケーリング (AutoScaleMode.Font) を適用しているとき、DockPanelの親フォームのフォントを変更すると、DockContentの子コントロールのスケーリングが正しく処理されないことがあります。そのときにはDockContentの表示前に同一のフォントを指定するか、PatchController.EnableFontInheritanceFix = falseとして、DockPanelのフォントが子コントロールに波及しないようにします。

myDockContent = new MyDockContent();

myDockContent.Font = this.Font;
myDockContent.Show(panel1, DockState.Float);

タブのボタン

DockPaneのタブのボタンはスケーリングが考慮されていないため、DockPaneを表示後に変更すると不適切に表示されます。c# - Resize dock pane tab strip text and buttons in Document docked DockContent - Stack Overflow