WisdomSoft - for your serial experiences.

3.3 ドックパネル

上下、左右、中央のそれぞれに要素を張り付けるドックパネルの使い方を説明します。中央にコンテンツを配置し、上下左右にバーや項目リストなどを配置する標準的なツールのレイアウトに適しています。

3.3.1 俯瞰風景

上下左右の空間にコントロールを配置し、中央に重要なドキュメントを表示するというレイアウトは、Web でも Windows アプリケーションでも、今日ではよく見られるようになった一般的なデザインです。何らかのコンテンツや操作パネルを、上下左右に配置し、中央に主となるコンテンツを表示するというレイアウトは、ウィンドウに表示する様々なコントロールを分割する基本構造となるでしょう。

こうしたレイアウトを実現するには System.Windows.Controls.DockPanel クラスを利用します。DockPanel は、子要素をパネルの上下左右の端に配置することができ、自動的に子要素のサイズを調整してくれます。

System.Windows.Controls.DockPanel クラス
System.Object 
   System.Windows.Threading.DispatcherObject 
     System.Windows.DependencyObject 
       System.Windows.Media.Visual 
         System.Windows.UIElement 
           System.Windows.FrameworkElement 
             System.Windows.Controls.Panel 
              System.Windows.Controls.DockPanel
public class DockPanel : Panel

やはり、子要素は Children プロパティから追加するものであり、基本的な操作方法は Panel クラスを継承しているので Canvas や StackPanel と同じです。このクラスのコンストラクタは、パラメータを受け取りません。

DockPanel クラスのコンストラクタ
public DockPanel ()

子要素を DockPanel の上下左右のどの部分に配置するかは DockPanel クラスの静的なメソッドから設定できます。考え方は Canvas クラスで子要素の座標を指定する方法と同じです。子要素の配置場所を設定するには SetDock() メソッドを、配置場所を取得するには GetDock() メソッドを使います。

DockPanel クラス SetDock() メソッド
public static void SetDock (UIElement element, Dock dock)
DockPanel クラス GetDock() メソッド
[AttachedPropertyBrowsableForChildrenAttribute] 
public static Dock GetDock (UIElement element)

element には、配置場所を設定、または取得する UIElement を指定します。dock には、新しく設定する子要素の配置場所を指定します。DockPanel に配置する上下左右の場所は System.Windows.Controls.Dock 列挙体で表されています。

System.Windows.Controls.Dock 列挙体
public enum Dock

Dock 列挙体には、上部を表す Top、下部を表す Bottom、左を表す Left、右を表す Right メンバが定義されています。SetDock() メソッドの dock パラメータには、Dock 列挙体のいずれかのメンバを設定してください。

コード1
using System;
using System.Windows;
using System.Windows.Controls;

class Test {
	[STAThread]
	public static void Main() {
		DockPanel panel = new DockPanel();
		Button[] buttons = new Button[5];
		for(int i = 0 ; i < buttons.Length ; i++) {
			buttons[i] = new Button();
			panel.Children.Add(buttons[i]);
		}

		buttons[0].Content = "Top";
		DockPanel.SetDock(buttons[0], Dock.Top);

		buttons[1].Content = "Bottom";
		DockPanel.SetDock(buttons[1], Dock.Bottom);

		buttons[2].Content = "Left";
		DockPanel.SetDock(buttons[2], Dock.Left);

		buttons[3].Content = "Right";
		DockPanel.SetDock(buttons[3], Dock.Right);

		buttons[4].Content = "Center";

		Window wnd = new Window();
		wnd.Content = panel;

		Application app = new Application();
		app.Run(wnd);
	}
}
実行結果
コード1 実行結果

コード1は、5 つの Button オブジェクトを DackPanel に追加し表示した例です。各ボタンは SetDock() メソッドから上下左右の場所を明示的に設定していますが、最後に追加したボタンだけは SetDock() を指定していません。

DockPanel クラスは、最後に追加した子要素が配置場所を設定していない場合、使用されていない残りの領域を使います。コード1の場合、上下左右全ての場所にボタンが配置されているため、残るは中央の領域全体ということになります。通常、この中央の領域にアプリケーションの主要なコンテンツが配置されることになるでしょう。

コード1の実行結果を見ると、"Top" ボタンと "Bottom" ボタンが横幅全体に伸ばされ、ウィンドウの端を占有しています。これに対して "Left" ボタンと "Right" ボタンはウィンドウの端を確保できていません。これは、DockPanel に追加された順番で決定します。例えば、Dock.Left と Dock.Right が設定されている子要素から先に追加した場合、その要素がパネルの端を占有します。

コード2
using System;
using System.Windows;
using System.Windows.Controls;

class Test {
	[STAThread]
	public static void Main() {
		DockPanel panel = new DockPanel();
		Button[] buttons = new Button[5];
		for(int i = 0 ; i < buttons.Length ; i++) {
			buttons[i] = new Button();
			panel.Children.Add(buttons[i]);
		}

		buttons[0].Content = "Left";
		DockPanel.SetDock(buttons[0], Dock.Left);

		buttons[1].Content = "Right";
		DockPanel.SetDock(buttons[1], Dock.Right);

		buttons[2].Content = "Top";
		DockPanel.SetDock(buttons[2], Dock.Top);

		buttons[3].Content = "Bottom";
		DockPanel.SetDock(buttons[3], Dock.Bottom);

		buttons[4].Content = "Center";

		Window wnd = new Window();
		wnd.Content = panel;

		Application app = new Application();
		app.Run(wnd);
	}
}
実行結果
コード2 実行結果

コード2の実行結果を見ると、コード1とは異なり、"Left" ボタンと "Right" ボタンが端を占有しています。

DockPanel は、必ず全ての領域に子要素を配置する必要はありません。例えば、DockLeft に操作用のコントロールを列挙している StackPanel を配置して、残りの領域は全て主要なコンテンツを表示する空間として利用することもできます。

コード3
using System;
using System.Windows;
using System.Windows.Controls;

class Test {
	[STAThread]
	public static void Main() {
		DockPanel panel = new DockPanel();

		Button[] buttons = new Button[3];
		for(int i = 0 ; i < buttons.Length ; i++) {
			buttons[i] = new Button();
			panel.Children.Add(buttons[i]);
		}

		buttons[0].Content = "Left";
		DockPanel.SetDock(buttons[0], Dock.Left);

		buttons[1].Content = "Top";
		DockPanel.SetDock(buttons[1], Dock.Top);

		buttons[2].Content = "Center";

		Window wnd = new Window();
		wnd.Content = panel;

		Application app = new Application();
		app.Run(wnd);
	}
}
実行結果
コード3 実行結果

コード3の場合、パネルの上と左にのみボタンを配置し、残りの部分は "Center" ボタンが占有しています。

DockPanel は、既定で最後に追加された子要素が残りの領域全体に広げられますが、この設定を LastChildFill プロパティで無効にすることができます。

DockPanel クラス LastChildFill プロパティ
public bool LastChildFill { get; set; }

LastChildFill が true の場合、最後に追加された子要素が残りの領域全体に広げられます。既定では true が設定されいるので、無効にする場合は false を設定してください。

コード4
using System;
using System.Windows;
using System.Windows.Controls;

class Test {
	[STAThread]
	public static void Main() {
		DockPanel panel = new DockPanel();
		panel.LastChildFill = false;

		Button[] buttons = new Button[5];
		for(int i = 0 ; i < buttons.Length ; i++) {
			buttons[i] = new Button();
			panel.Children.Add(buttons[i]);
		}

		buttons[0].Content = "Top";
		DockPanel.SetDock(buttons[0], Dock.Top);

		buttons[1].Content = "Bottom";
		DockPanel.SetDock(buttons[1], Dock.Bottom);

		buttons[2].Content = "Left";
		DockPanel.SetDock(buttons[2], Dock.Left);

		buttons[3].Content = "Right";
		DockPanel.SetDock(buttons[3], Dock.Right);

		buttons[4].Content = "Center";

		Window wnd = new Window();
		wnd.Content = panel;

		Application app = new Application();
		app.Run(wnd);
	}
}
実行結果
コード4 実行結果

コード4は、DockPanel オブジェクトの LastChildFill プロパティが false に設定されています。そのため、中央に配置されている最後に追加されたボタンが、領域全体を使っていないことが確認できます。