3.3 ドックパネル
3.3.1 俯瞰風景
上下左右の空間にコントロールを配置し、中央に重要なドキュメントを表示するというレイアウトは、Web でも Windows アプリケーションでも、今日ではよく見られるようになった一般的なデザインです。何らかのコンテンツや操作パネルを、上下左右に配置し、中央に主となるコンテンツを表示するというレイアウトは、ウィンドウに表示する様々なコントロールを分割する基本構造となるでしょう。
こうしたレイアウトを実現するには System.Windows.Controls.DockPanel クラスを利用します。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 と同じです。このクラスのコンストラクタは、パラメータを受け取りません。
public DockPanel ()
子要素を DockPanel の上下左右のどの部分に配置するかは DockPanel クラスの静的なメソッドから設定できます。考え方は Canvas クラスで子要素の座標を指定する方法と同じです。子要素の配置場所を設定するには SetDock() メソッドを、配置場所を取得するには GetDock() メソッドを使います。
public static void SetDock (UIElement element, Dock dock)
[AttachedPropertyBrowsableForChildrenAttribute] public static Dock GetDock (UIElement element)
element には、配置場所を設定、または取得する UIElement を指定します。dock には、新しく設定する子要素の配置場所を指定します。DockPanel に配置する上下左右の場所は System.Windows.Controls.Dock 列挙体で表されています。
public enum Dock
Dock 列挙体には、上部を表す Top、下部を表す Bottom、左を表す Left、右を表す Right メンバが定義されています。SetDock() メソッドの dock パラメータには、Dock 列挙体のいずれかのメンバを設定してください。
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は、5 つの Button オブジェクトを DackPanel に追加し表示した例です。各ボタンは SetDock() メソッドから上下左右の場所を明示的に設定していますが、最後に追加したボタンだけは SetDock() を指定していません。
DockPanel クラスは、最後に追加した子要素が配置場所を設定していない場合、使用されていない残りの領域を使います。コード1の場合、上下左右全ての場所にボタンが配置されているため、残るは中央の領域全体ということになります。通常、この中央の領域にアプリケーションの主要なコンテンツが配置されることになるでしょう。
コード1の実行結果を見ると、"Top" ボタンと "Bottom" ボタンが横幅全体に伸ばされ、ウィンドウの端を占有しています。これに対して "Left" ボタンと "Right" ボタンはウィンドウの端を確保できていません。これは、DockPanel に追加された順番で決定します。例えば、Dock.Left と Dock.Right が設定されている子要素から先に追加した場合、その要素がパネルの端を占有します。
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の実行結果を見ると、コード1とは異なり、"Left" ボタンと "Right" ボタンが端を占有しています。
DockPanel は、必ず全ての領域に子要素を配置する必要はありません。例えば、DockLeft に操作用のコントロールを列挙している StackPanel を配置して、残りの領域は全て主要なコンテンツを表示する空間として利用することもできます。
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の場合、パネルの上と左にのみボタンを配置し、残りの部分は "Center" ボタンが占有しています。
DockPanel は、既定で最後に追加された子要素が残りの領域全体に広げられますが、この設定を LastChildFill プロパティで無効にすることができます。
public bool LastChildFill { get; set; }
LastChildFill が true の場合、最後に追加された子要素が残りの領域全体に広げられます。既定では true が設定されいるので、無効にする場合は false を設定してください。
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は、DockPanel オブジェクトの LastChildFill プロパティが false に設定されています。そのため、中央に配置されている最後に追加されたボタンが、領域全体を使っていないことが確認できます。