面板概觀
更新:2007 年 11 月
Panel 項目是可控制項目呈現方式的元件 - 即項目的大小與維度、位置及其子內容的排列。Windows Presentation Foundation (WPF) 提供了多項預先定義的 Panel 項目及用以建構自訂 Panel 項目的功能。
本主題包含下列章節。
面板類別
面板項目的一般成員
衍生面板項目
使用者介面面板
巢狀面板項目
自訂面板項目
當地語系化/全球化支援
相關主題
面板類別
Panel 是 Windows Presentation Foundation (WPF) 中所有支援配置之項目的基底類別 (Base Class)。衍生 Panel 項目可用以透過可延伸標記語言 (XAML) 與程式碼來定位及排列 UIElements。
WPF 包含一套完善的衍生面板實作可進行許多複雜的配置。這些衍生類別會公開相關的屬性與方法,以運用在最標準的使用者介面 (UI) 案例中。開發人員若找不到符合其需求的子排列行為,可以覆寫 ArrangeOverride 與 MeasureOverride 方法以建立新配置。如需自訂配置行為的詳細資訊,請參閱自訂面板項目。
XAMLPad
XAMLPad 這項工具靠著可即時剖析標記並在視窗中顯示結果,來簡化可延伸標記語言 (XAML) 架構使用者介面的開發過程。此工具非常適用於進行配置。您可以開啟應用程式,以檢視本主題中各種可延伸標記語言 (XAML) 範例的結果。如需詳細資訊,請參閱 XAMLPad。
面板的一般成員
所有 Panel 項目都支援 FrameworkElement 所定義的基底大小與定位,包括 Height、Width、HorizontalAlignment、VerticalAlignment、Margin 與 LayoutTransform。如需 FrameworkElement 所定義之定位屬性的其他資訊,請參閱對齊、邊界和填補概觀。
Panel 會公開了解及使用配置時所不可或缺的其他屬性。Background 屬性可用以透過 Brush 填滿衍生面板項目之邊界間的區域。Children 代表組成 Panel 之 UIElements 的子集合。InternalChildren 代表 Children 集合的內容加上資料繫結所產生的成員。兩者都包含父 Panel 內裝載之子項目的 UIElementCollection。
面板也會公開 ZIndex 屬性,用以達成衍生 Panel 中的分層順序。就面板 Children 集合的成員而言,ZIndex 值較高者會顯示在 ZIndex 值較低者之前。對於 Canvas 與 Grid 等允許子系共用相同座標空間的面板,這特別有用。
Panel 也會定義 OnRender 方法,用以覆寫 Panel 的預設表示行為。
附加屬性
衍生面板項目可廣泛運用附加屬性。附加屬性是一種特殊形式的相依性屬性,這種屬性沒有傳統的 Common Language Runtime (CLR) 屬性「包裝函式」。附加屬性具有可延伸標記語言 (XAML) 的特殊語法,可見於下列數個範例中。
附加屬性的其中一個用途,就是讓子項目能夠儲存父項目實際定義之屬性的唯一值。具有此功能的應用程式可讓子項目告知父代其本身在使用者介面 (UI) 中所需的呈現方式,這在進行應用程式配置時極為有用。如需詳細資訊,請參閱附加屬性概觀。
衍生面板項目
許多物件都衍生自 Panel,但它們並非全都可做為根配置提供者。特別針對建立應用程式 UI 而設計的已定義面板類別有六種 (Canvas、DockPanel、Grid、StackPanel、VirtualizingStackPanel 與 WrapPanel)。
每個面板項目都封裝其本身的特殊功能,如下表所示。
項目名稱 |
UI 面板? |
描述 |
---|---|---|
可以 |
定義一個區域,您可以在這個區域內依據相對於 Canvas 區域的座標,明確放置子項目。 |
|
可以 |
定義一個區域,您可以在這個區域內水平或垂直排列子項目 (彼此相對)。 |
|
可以 |
||
可以 |
將子項目排列成可呈水平或垂直方向的單行。 |
|
不可以 |
處理 TabControl 中索引標籤按鈕的配置。 |
|
不可以 |
排列 ToolBar 控制項內的內容。 |
|
不可以 |
UniformGrid 可用以在儲存格大小皆相等的方格內排列子系。 |
|
不可以 |
針對可「虛擬化」其子集合的面板提供基底類別。 |
|
可以 |
將內容排列及虛擬化在水平或垂直方向的單行。 |
|
可以 |
WrapPanel 可將子項目從左到右依序放置,並在包含的方塊邊緣將內容中斷,換到下一行。之後的順序則根據 Orientation 屬性值而定,可循序由上至下或由右至左。 |
使用者介面面板
WPF 中有六種可用的面板類別,這些類別都以最佳化的方式來支援 UI 案例:Canvas、DockPanel、Grid、StackPanel、VirtualizingStackPanel 與 WrapPanel。這些面板項目都具有易用、多樣化與可擴充的特點,適用於大部分的應用程式。
各個衍生 Panel 項目會以不同的方式處理大小條件約束。若能了解 Panel 如何處理水平或垂直方向的條件約束,將使配置更符合預期。
面板名稱 |
x 維度 |
y 維度 |
---|---|---|
限制為內容 |
限制為內容 |
|
受限制 |
受限制 |
|
StackPanel (垂直方向) |
受限制 |
限制為內容 |
StackPanel (水平方向) |
限制為內容 |
受限制 |
受限制 |
受限制,但在 Auto 套用至資料列與資料行時例外 |
|
限制為內容 |
限制為內容 |
本文稍後將提供這些項目的詳細說明與使用方式範例。
畫布
Canvas 項目可讓內容根據 x 與 y 的絕對座標進行定位。項目可在唯一的位置上繪製,若項目位於相同的座標上,則其顯示於標記中的順序將決定其繪製順序。
Canvas 可為任何 Panel 提供最富彈性的配置支援。高度與寬度屬性可用以定義畫布區域,而畫布內的項目會被指定相對於父 Canvas 區域的絕對座標。Left、Top、Right 與 Bottom 這四個附加屬性,可讓開發人員妥善控制 Canvas 內的物件放置,進而精確地定位及排列畫面上的項目。
畫布內的 ClipToBounds
Canvas 可將子項目放在畫面上的任意位置,即使在其本身定義的 Height 與 Width 以外的座標上也是如此。此外,Canvas 並不會受其子系的大小影響。因此,子項目有可能會在父 Canvas 的週框 (bounding rectangle) 以外繪製其他項目。Canvas 的預設行為就是讓子系能在父 Canvas 的邊界之外繪製。若不使用此行為,可將 ClipToBounds 屬性設為 true。這會使 Canvas 裁剪為其本身的大小。Canvas 是唯一允許子系在其邊界之外繪製的配置項目。
此行為將在 寬度屬性比較範例中以圖形說明。
定義和使用畫布
Canvas 只要透過可延伸標記語言 (XAML) 或程式碼即可具現化 (Instantiated)。下列範例會示範如何使用 Canvas 以絕對的方式定位內容。此程式碼會產生三個 100 像素的方形。第一個方形為紅色,其左上角 (x, y) 位置指定為 (0, 0)。第二個方形為綠色,其左上角位置 (100, 100) 正好位於第一個方形的右下角。第三個方形為藍色,其左上角位置為 (50, 50),因此會涵蓋第一個方形的右下角四分之一,以及第二個方形的左上角四分之一。因為第三個方形最後才放置,所以會顯示在另外兩個方形上面,也就是說,重疊的部分會呈現第三個方塊的色彩。
WindowTitle = "Canvas Sample"
'Create a Canvas as the root Panel
Dim myParentCanvas As New Canvas()
myParentCanvas.Width = 400
myParentCanvas.Height = 400
' Define child Canvas elements
Dim myCanvas1 As New Canvas()
myCanvas1.Background = Brushes.Red
myCanvas1.Height = 100
myCanvas1.Width = 100
Canvas.SetTop(myCanvas1, 0)
Canvas.SetLeft(myCanvas1, 0)
Dim myCanvas2 As New Canvas()
myCanvas2.Background = Brushes.Green
myCanvas2.Height = 100
myCanvas2.Width = 100
Canvas.SetTop(myCanvas2, 100)
Canvas.SetLeft(myCanvas2, 100)
Dim myCanvas3 As New Canvas()
myCanvas3.Background = Brushes.Blue
myCanvas3.Height = 100
myCanvas3.Width = 100
Canvas.SetTop(myCanvas3, 50)
Canvas.SetLeft(myCanvas3, 50)
' Add child elements to the Canvas' Children collection
myParentCanvas.Children.Add(myCanvas1)
myParentCanvas.Children.Add(myCanvas2)
myParentCanvas.Children.Add(myCanvas3)
' Add the parent Canvas as the Content of the Window Object
Me.Content = myParentCanvas
// Create the application's main window
mainWindow = new Window ();
mainWindow.Title = "Canvas Sample";
// Create the Canvas
myParentCanvas = new Canvas();
myParentCanvas.Width = 400;
myParentCanvas.Height = 400;
// Define child Canvas elements
myCanvas1 = new Canvas();
myCanvas1.Background = Brushes.Red;
myCanvas1.Height = 100;
myCanvas1.Width = 100;
Canvas.SetTop(myCanvas1, 0);
Canvas.SetLeft(myCanvas1, 0);
myCanvas2 = new Canvas();
myCanvas2.Background = Brushes.Green;
myCanvas2.Height = 100;
myCanvas2.Width = 100;
Canvas.SetTop(myCanvas2, 100);
Canvas.SetLeft(myCanvas2, 100);
myCanvas3 = new Canvas();
myCanvas3.Background = Brushes.Blue;
myCanvas3.Height = 100;
myCanvas3.Width = 100;
Canvas.SetTop(myCanvas3, 50);
Canvas.SetLeft(myCanvas3, 50);
// Add child elements to the Canvas' Children collection
myParentCanvas.Children.Add(myCanvas1);
myParentCanvas.Children.Add(myCanvas2);
myParentCanvas.Children.Add(myCanvas3);
// Add the parent Canvas as the Content of the Window Object
mainWindow.Content = myParentCanvas;
mainWindow.Show ();
<Page WindowTitle="Canvas Sample" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Canvas Height="400" Width="400">
<Canvas Height="100" Width="100" Top="0" Left="0" Background="Red"/>
<Canvas Height="100" Width="100" Top="100" Left="100" Background="Green"/>
<Canvas Height="100" Width="100" Top="50" Left="50" Background="Blue"/>
</Canvas>
</Page>
完成編譯的應用程式會產生新的 UI,如下所示。
DockPanel
DockPanel 項目可使用附加的 Dock 屬性,沿著容器的邊緣放置內容。當 Dock 設為 Top 或 Bottom 時,它會讓子項目彼此上下放置。當 Dock 設為 Left 或 Right 時,它會讓子項目彼此左右放置。LastChildFill 屬性可決定最後加入為 DockPanel 之子系的項目位置。
您可以使用 DockPanel 來放置一組相關的控制項,例如一組按鈕。或者,也可以使用它來建立「附有窗格的」UI,類似於 Microsoft Outlook 中的功能。
隨內容調整大小
若未指定其 Height 與 Width 屬性,DockPanel 即會調整為其內容的大小。大小會增加或減少,以容納其子項目的大小。但是,若已指定這些屬性,並且已沒有空間可供下一個指定的子項目使用,DockPanel 則不會顯示該子項目或後續的子項目,也不會測量後續的子項目。
LastChildFill
根據預設,DockPanel 項目的最後一個子系會「填滿」未配置的剩餘空間。若不使用此行為,請將 LastChildFill 屬性設為 false。
定義和使用 DockPanel
下列範例會示範如何使用 DockPanel 來分割空間。有五個 Border 項目會加入成為 DockPanel 的子系。每個項目會使用 DockPanel 的不同定位屬性進行空間分割。最後一個項目會「填滿」未配置的剩餘空間。
WindowTitle = "DockPanel Sample"
'Create a DockPanel as the root Panel
Dim myDockPanel As New DockPanel()
myDockPanel.LastChildFill = True
' Define the child content
Dim myBorder1 As New Border()
myBorder1.Height = 25
myBorder1.Background = Brushes.SkyBlue
myBorder1.BorderBrush = Brushes.Black
myBorder1.BorderThickness = New Thickness(1)
DockPanel.SetDock(myBorder1, Dock.Top)
Dim myTextBlock1 As New TextBlock()
myTextBlock1.Foreground = Brushes.Black
myTextBlock1.Text = "Dock = Top"
myBorder1.Child = myTextBlock1
Dim myBorder2 As New Border()
myBorder2.Height = 25
myBorder2.Background = Brushes.SkyBlue
myBorder2.BorderBrush = Brushes.Black
myBorder2.BorderThickness = New Thickness(1)
DockPanel.SetDock(myBorder2, Dock.Top)
Dim myTextBlock2 As New TextBlock()
myTextBlock2.Foreground = Brushes.Black
myTextBlock2.Text = "Dock = Top"
myBorder2.Child = myTextBlock2
Dim myBorder3 As New Border()
myBorder3.Height = 25
myBorder3.Background = Brushes.LemonChiffon
myBorder3.BorderBrush = Brushes.Black
myBorder3.BorderThickness = New Thickness(1)
DockPanel.SetDock(myBorder3, Dock.Bottom)
Dim myTextBlock3 As New TextBlock()
myTextBlock3.Foreground = Brushes.Black
myTextBlock3.Text = "Dock = Bottom"
myBorder3.Child = myTextBlock3
Dim myBorder4 As New Border()
myBorder4.Width = 200
myBorder4.Background = Brushes.PaleGreen
myBorder4.BorderBrush = Brushes.Black
myBorder4.BorderThickness = New Thickness(1)
DockPanel.SetDock(myBorder4, Dock.Left)
Dim myTextBlock4 As New TextBlock()
myTextBlock4.Foreground = Brushes.Black
myTextBlock4.Text = "Dock = Left"
myBorder4.Child = myTextBlock4
Dim myBorder5 As New Border()
myBorder5.Background = Brushes.White
myBorder5.BorderBrush = Brushes.Black
myBorder5.BorderThickness = New Thickness(1)
Dim myTextBlock5 As New TextBlock()
myTextBlock5.Foreground = Brushes.Black
myTextBlock5.Text = "This content will Fill the remaining space"
myBorder5.Child = myTextBlock5
' Add child elements to the DockPanel Children collection
myDockPanel.Children.Add(myBorder1)
myDockPanel.Children.Add(myBorder2)
myDockPanel.Children.Add(myBorder3)
myDockPanel.Children.Add(myBorder4)
myDockPanel.Children.Add(myBorder5)
Me.Content = myDockPanel
// Create the application's main window
mainWindow = new Window ();
mainWindow.Title = "DockPanel Sample";
// Create the DockPanel
DockPanel myDockPanel = new DockPanel();
myDockPanel.LastChildFill = true;
// Define the child content
Border myBorder1 = new Border();
myBorder1.Height = 25;
myBorder1.Background = Brushes.SkyBlue;
myBorder1.BorderBrush = Brushes.Black;
myBorder1.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder1, Dock.Top);
TextBlock myTextBlock1 = new TextBlock();
myTextBlock1.Foreground = Brushes.Black;
myTextBlock1.Text = "Dock = Top";
myBorder1.Child = myTextBlock1;
Border myBorder2 = new Border();
myBorder2.Height = 25;
myBorder2.Background = Brushes.SkyBlue;
myBorder2.BorderBrush = Brushes.Black;
myBorder2.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder2, Dock.Top);
TextBlock myTextBlock2 = new TextBlock();
myTextBlock2.Foreground = Brushes.Black;
myTextBlock2.Text = "Dock = Top";
myBorder2.Child = myTextBlock2;
Border myBorder3 = new Border();
myBorder3.Height = 25;
myBorder3.Background = Brushes.LemonChiffon;
myBorder3.BorderBrush = Brushes.Black;
myBorder3.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder3, Dock.Bottom);
TextBlock myTextBlock3 = new TextBlock();
myTextBlock3.Foreground = Brushes.Black;
myTextBlock3.Text = "Dock = Bottom";
myBorder3.Child = myTextBlock3;
Border myBorder4 = new Border();
myBorder4.Width = 200;
myBorder4.Background = Brushes.PaleGreen;
myBorder4.BorderBrush = Brushes.Black;
myBorder4.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder4, Dock.Left);
TextBlock myTextBlock4 = new TextBlock();
myTextBlock4.Foreground = Brushes.Black;
myTextBlock4.Text = "Dock = Left";
myBorder4.Child = myTextBlock4;
Border myBorder5 = new Border();
myBorder5.Background = Brushes.White;
myBorder5.BorderBrush = Brushes.Black;
myBorder5.BorderThickness = new Thickness(1);
TextBlock myTextBlock5 = new TextBlock();
myTextBlock5.Foreground = Brushes.Black;
myTextBlock5.Text = "This content will Fill the remaining space";
myBorder5.Child = myTextBlock5;
// Add child elements to the DockPanel Children collection
myDockPanel.Children.Add(myBorder1);
myDockPanel.Children.Add(myBorder2);
myDockPanel.Children.Add(myBorder3);
myDockPanel.Children.Add(myBorder4);
myDockPanel.Children.Add(myBorder5);
// Add the parent Canvas as the Content of the Window Object
mainWindow.Content = myDockPanel;
mainWindow.Show ();
<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" WindowTitle="DockPanel Sample">
<DockPanel LastChildFill="True">
<Border Height="25" Background="SkyBlue" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Top">
<TextBlock Foreground="Black">Dock = "Top"</TextBlock>
</Border>
<Border Height="25" Background="SkyBlue" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Top">
<TextBlock Foreground="Black">Dock = "Top"</TextBlock>
</Border>
<Border Height="25" Background="LemonChiffon" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Bottom">
<TextBlock Foreground="Black">Dock = "Bottom"</TextBlock>
</Border>
<Border Width="200" Background="PaleGreen" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Left">
<TextBlock Foreground="Black">Dock = "Left"</TextBlock>
</Border>
<Border Background="White" BorderBrush="Black" BorderThickness="1">
<TextBlock Foreground="Black">This content will "Fill" the remaining space</TextBlock>
</Border>
</DockPanel>
</Page>
完成編譯的應用程式會產生新的 UI,如下所示。
格線
Grid 項目合併了絕對定位與表格式資料控制的功能。Grid 可讓您輕鬆地放置項目及設定其樣式。Grid 可讓您定義富彈性的資料列與資料行群組,甚至提供在多個 Grid 項目間共用大小資訊的機制。
方格和資料表有何不同?
Table 與 Grid 會共用某些通用功能,但兩者分別適用於不同的情況。Table 的設計適合在非固定格式內容中使用 (如需非固定格式內容的詳細資訊,請參閱非固定格式文件概觀)。方格則適用於表單內 (基本上,只要是非固定格式內容都適用)。在 FlowDocument 內,Table 支援分頁、資料行重新排列與內容選取等非固定格式內容行為,而 Grid 則否。另一方面,Grid 適用於 FlowDocument 以外的地方,其原因眾多,包括 Grid 會根據資料列與資料行索引加入項目,Table 則否。Grid 項目允許子內容進行分層,使單一「儲存格」內可有多個項目存在。而 Table 不支援分層。Grid 的子項目可放在相對於其「儲存格」界限區域的絕對位置,但 Table 不支援此功能。最後,Grid 的粗細小於 Table。
資料行與資料列的縮放行為
定義在 Grid 中的資料行和資料列可利用 Star 縮放,按照比例分配剩餘空間。選取 Star 做為資料列或資料行的高度或寬度時,該資料行或資料列會接收加權比例的剩餘可用空間。這種情形與 Auto 相反,其會根據資料行或資料列中的內容大小來平均分配空間。使用可延伸標記語言 (XAML) 時,此值會以 * 或 2* 表示。如為前者,資料列或資料行會獲得一倍的可用空間,如為後者,則會獲得兩倍的可用空間,依此類推。如需星號大小的其他資訊,請參閱使用星號縮放範例範例。若將此按照比例分配空間的技術與 Stretch 的 HorizontalAlignment 和 VerticalAlignment 值結合,則可依畫面空間的百分比來分割配置空間。Grid 是唯一可以用這種方式來分配空間的配置面板。
定義和使用方格
下列範例會示範如何建置類似於 Windows [開始] 功能表的 [執行] 對話方塊上的 UI。
'Create a Grid as the root Panel element.
Dim myGrid As New Grid()
myGrid.Height = 165
myGrid.Width = 425
myGrid.Background = Brushes.Gainsboro
myGrid.ShowGridLines = True
myGrid.HorizontalAlignment = Windows.HorizontalAlignment.Left
myGrid.VerticalAlignment = Windows.VerticalAlignment.Top
' Define and Add the Rows and Columns.
Dim colDef1 As New ColumnDefinition
colDef1.Width = New GridLength(1, GridUnitType.Auto)
Dim colDef2 As New ColumnDefinition
colDef2.Width = New GridLength(1, GridUnitType.Star)
Dim colDef3 As New ColumnDefinition
colDef3.Width = New GridLength(1, GridUnitType.Star)
Dim colDef4 As New ColumnDefinition
colDef4.Width = New GridLength(1, GridUnitType.Star)
Dim colDef5 As New ColumnDefinition
colDef5.Width = New GridLength(1, GridUnitType.Star)
myGrid.ColumnDefinitions.Add(colDef1)
myGrid.ColumnDefinitions.Add(colDef2)
myGrid.ColumnDefinitions.Add(colDef3)
myGrid.ColumnDefinitions.Add(colDef4)
myGrid.ColumnDefinitions.Add(colDef5)
Dim rowDef1 As New RowDefinition
rowDef1.Height = New GridLength(1, GridUnitType.Auto)
Dim rowDef2 As New RowDefinition
rowDef2.Height = New GridLength(1, GridUnitType.Auto)
Dim rowDef3 As New Controls.RowDefinition
rowDef3.Height = New GridLength(1, GridUnitType.Star)
Dim rowDef4 As New RowDefinition
rowDef4.Height = New GridLength(1, GridUnitType.Auto)
myGrid.RowDefinitions.Add(rowDef1)
myGrid.RowDefinitions.Add(rowDef2)
myGrid.RowDefinitions.Add(rowDef3)
myGrid.RowDefinitions.Add(rowDef4)
' Add the Image.
Dim img1 As New Image
img1.Source = New System.Windows.Media.Imaging.BitmapImage(New Uri("runicon.png", UriKind.Relative))
Grid.SetRow(img1, 0)
Grid.SetColumn(img1, 0)
myGrid.Children.Add(img1)
' Add the main application dialog.
Dim txt1 As New TextBlock
txt1.Text = "Type the name of a program, document, or Internet resource, and Windows will open it for you."
txt1.TextWrapping = TextWrapping.Wrap
Grid.SetColumnSpan(txt1, 4)
Grid.SetRow(txt1, 0)
Grid.SetColumn(txt1, 1)
myGrid.Children.Add(txt1)
' Add the second TextBlock Cell to the Grid.
Dim txt2 As New TextBlock
txt2.Text = "Open:"
Grid.SetRow(txt2, 1)
Grid.SetColumn(txt2, 0)
myGrid.Children.Add(txt2)
' Add the TextBox control.
Dim tb1 As New TextBox
Grid.SetRow(tb1, 1)
Grid.SetColumn(tb1, 1)
Grid.SetColumnSpan(tb1, 5)
myGrid.Children.Add(tb1)
' Add the Button controls.
Dim button1 As New Button
Dim button2 As New Button
Dim button3 As New Button
button1.Content = "OK"
button1.Margin = New Thickness(10, 0, 10, 15)
button2.Content = "Cancel"
button2.Margin = New Thickness(10, 0, 10, 15)
button3.Content = "Browse ..."
button3.Margin = New Thickness(10, 0, 10, 15)
Grid.SetRow(button1, 3)
Grid.SetColumn(button1, 2)
Grid.SetRow(button2, 3)
Grid.SetColumn(button2, 3)
Grid.SetRow(button3, 3)
Grid.SetColumn(button3, 4)
myGrid.Children.Add(button1)
myGrid.Children.Add(button2)
myGrid.Children.Add(button3)
Me.Content = myGrid
// Create the Grid.
grid1 = new Grid ();
grid1.Background = Brushes.Gainsboro;
grid1.HorizontalAlignment = HorizontalAlignment.Left;
grid1.VerticalAlignment = VerticalAlignment.Top;
grid1.ShowGridLines = true;
grid1.Width = 425;
grid1.Height = 165;
// Define the Columns.
colDef1 = new ColumnDefinition();
colDef1.Width = new GridLength(1, GridUnitType.Auto);
colDef2 = new ColumnDefinition();
colDef2.Width = new GridLength(1, GridUnitType.Star);
colDef3 = new ColumnDefinition();
colDef3.Width = new GridLength(1, GridUnitType.Star);
colDef4 = new ColumnDefinition();
colDef4.Width = new GridLength(1, GridUnitType.Star);
colDef5 = new ColumnDefinition();
colDef5.Width = new GridLength(1, GridUnitType.Star);
grid1.ColumnDefinitions.Add(colDef1);
grid1.ColumnDefinitions.Add(colDef2);
grid1.ColumnDefinitions.Add(colDef3);
grid1.ColumnDefinitions.Add(colDef4);
grid1.ColumnDefinitions.Add(colDef5);
// Define the Rows.
rowDef1 = new RowDefinition();
rowDef1.Height = new GridLength(1, GridUnitType.Auto);
rowDef2 = new RowDefinition();
rowDef2.Height = new GridLength(1, GridUnitType.Auto);
rowDef3 = new RowDefinition();
rowDef3.Height = new GridLength(1, GridUnitType.Star);
rowDef4 = new RowDefinition();
rowDef4.Height = new GridLength(1, GridUnitType.Auto);
grid1.RowDefinitions.Add(rowDef1);
grid1.RowDefinitions.Add(rowDef2);
grid1.RowDefinitions.Add(rowDef3);
grid1.RowDefinitions.Add(rowDef4);
// Add the Image.
img1 = new Image();
img1.Source = new System.Windows.Media.Imaging.BitmapImage(new Uri("runicon.png", UriKind.Relative));
Grid.SetRow(img1, 0);
Grid.SetColumn(img1, 0);
// Add the main application dialog.
txt1 = new TextBlock();
txt1.Text = "Type the name of a program, folder, document, or Internet resource, and Windows will open it for you.";
txt1.TextWrapping = TextWrapping.Wrap;
Grid.SetColumnSpan(txt1, 4);
Grid.SetRow(txt1, 0);
Grid.SetColumn(txt1, 1);
// Add the second text cell to the Grid.
txt2 = new TextBlock();
txt2.Text = "Open:";
Grid.SetRow(txt2, 1);
Grid.SetColumn(txt2, 0);
// Add the TextBox control.
tb1 = new TextBox();
Grid.SetRow(tb1, 1);
Grid.SetColumn(tb1, 1);
Grid.SetColumnSpan(tb1, 5);
// Add the buttons.
button1 = new Button();
button2 = new Button();
button3 = new Button();
button1.Content = "OK";
button2.Content = "Cancel";
button3.Content = "Browse ...";
Grid.SetRow(button1, 3);
Grid.SetColumn(button1, 2);
button1.Margin = new Thickness(10, 0, 10, 15);
button2.Margin = new Thickness(10, 0, 10, 15);
button3.Margin = new Thickness(10, 0, 10, 15);
Grid.SetRow(button2, 3);
Grid.SetColumn(button2, 3);
Grid.SetRow(button3, 3);
Grid.SetColumn(button3, 4);
grid1.Children.Add(img1);
grid1.Children.Add(txt1);
grid1.Children.Add(txt2);
grid1.Children.Add(tb1);
grid1.Children.Add(button1);
grid1.Children.Add(button2);
grid1.Children.Add(button3);
mainWindow.Content = grid1;
<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="Grid Run Dialog Sample"
WindowWidth="425"
WindowHeight="225">
<Grid Background="#DCDCDC"
Width="425"
Height="165"
HorizontalAlignment="Left"
VerticalAlignment="Top"
ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Grid.Column="0" Grid.Row="0" Source="RunIcon.png" />
<TextBlock Grid.Column="1" Grid.ColumnSpan="4" Grid.Row="0" TextWrapping="Wrap">
Type the name of a program, folder, document, or
Internet resource, and Windows will open it for you.
</TextBlock>
<TextBlock Grid.Column="0" Grid.Row="1">Open:</TextBlock>
<TextBox Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="5" />
<Button Margin="10, 0, 10, 15" Grid.Row="3" Grid.Column="2">OK</Button>
<Button Margin="10, 0, 10, 15" Grid.Row="3" Grid.Column="3">Cancel</Button>
<Button Margin="10, 0, 10, 15" Grid.Row="3" Grid.Column="4">Browse ...</Button>
</Grid>
</Page>
完成編譯的應用程式會產生新的 UI,如下所示。
StackPanel
StackPanel 可讓您以指定的方向「堆疊」項目。預設的堆疊方向為垂直。Orientation 屬性可用以控制內容方向。
StackPanel 與 DockPanel 的比較
雖然 DockPanel 也會「堆疊」子項目,但 DockPanel 與 StackPanel 在某些使用案例中不會產生類似的結果。例如,子項目的順序會影響它們在 DockPanel 中的大小,但在 StackPanel 中則沒有影響。這是因為 StackPanel 會測量於 PositiveInfinity 堆疊的方向,但是 DockPanel 只會測量可用的大小。
下列範例說明此主要差異。
'Add root Grid
Dim myGrid As New Grid
myGrid.Width = 175
myGrid.Height = 150
Dim myRowDef1 As New RowDefinition
Dim myRowDef2 As New RowDefinition
myGrid.RowDefinitions.Add(myRowDef1)
myGrid.RowDefinitions.Add(myRowDef2)
'Define the DockPanel
Dim myDockPanel As New DockPanel
Grid.SetRow(myDockPanel, 0)
'Define an Image and Source.
Dim myImage As New Image
Dim bi As New BitmapImage
bi.BeginInit()
bi.UriSource = New Uri("smiley_stackpanel.png", UriKind.Relative)
bi.EndInit()
myImage.Source = bi
Dim myImage2 As New Image
Dim bi2 As New BitmapImage
bi2.BeginInit()
bi2.UriSource = New Uri("smiley_stackpanel.png", UriKind.Relative)
bi2.EndInit()
myImage2.Source = bi2
Dim myImage3 As New Image
Dim bi3 As New BitmapImage
bi3.BeginInit()
bi3.UriSource = New Uri("smiley_stackpanel.PNG", UriKind.Relative)
bi3.EndInit()
myImage3.Stretch = Stretch.Fill
myImage3.Source = bi3
'Add the images to the parent DockPanel.
myDockPanel.Children.Add(myImage)
myDockPanel.Children.Add(myImage2)
myDockPanel.Children.Add(myImage3)
'Define a StackPanel.
Dim myStackPanel As New StackPanel
myStackPanel.Orientation = Orientation.Horizontal
Grid.SetRow(myStackPanel, 1)
Dim myImage4 As New Image
Dim bi4 As New BitmapImage
bi4.BeginInit()
bi4.UriSource = New Uri("smiley_stackpanel.png", UriKind.Relative)
bi4.EndInit()
myImage4.Source = bi4
Dim myImage5 As New Image
Dim bi5 As New BitmapImage
bi5.BeginInit()
bi5.UriSource = New Uri("smiley_stackpanel.png", UriKind.Relative)
bi5.EndInit()
myImage5.Source = bi5
Dim myImage6 As New Image
Dim bi6 As New BitmapImage
bi6.BeginInit()
bi6.UriSource = New Uri("smiley_stackpanel.PNG", UriKind.Relative)
bi6.EndInit()
myImage6.Stretch = Stretch.Fill
myImage6.Source = bi6
'Add the images to the parent StackPanel.
myStackPanel.Children.Add(myImage4)
myStackPanel.Children.Add(myImage5)
myStackPanel.Children.Add(myImage6)
'Add the layout panels as children of the Grid
myGrid.Children.Add(myDockPanel)
myGrid.Children.Add(myStackPanel)
// Create the application's main window
mainWindow = new Window ();
mainWindow.Title = "StackPanel vs. DockPanel";
// Add root Grid
myGrid = new Grid();
myGrid.Width = 175;
myGrid.Height = 150;
RowDefinition myRowDef1 = new RowDefinition();
RowDefinition myRowDef2 = new RowDefinition();
myGrid.RowDefinitions.Add(myRowDef1);
myGrid.RowDefinitions.Add(myRowDef2);
// Define the DockPanel
myDockPanel = new DockPanel();
Grid.SetRow(myDockPanel, 0);
//Define an Image and Source
Image myImage = new Image();
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri("smiley_stackpanel.png", UriKind.Relative);
bi.EndInit();
myImage.Source = bi;
Image myImage2 = new Image();
BitmapImage bi2 = new BitmapImage();
bi2.BeginInit();
bi2.UriSource = new Uri("smiley_stackpanel.png", UriKind.Relative);
bi2.EndInit();
myImage2.Source = bi2;
Image myImage3 = new Image();
BitmapImage bi3 = new BitmapImage();
bi3.BeginInit();
bi3.UriSource = new Uri("smiley_stackpanel.PNG", UriKind.Relative);
bi3.EndInit();
myImage3.Stretch = Stretch.Fill;
myImage3.Source = bi3;
// Add the images to the parent DockPanel
myDockPanel.Children.Add(myImage);
myDockPanel.Children.Add(myImage2);
myDockPanel.Children.Add(myImage3);
//Define a StackPanel
myStackPanel = new StackPanel();
myStackPanel.Orientation = Orientation.Horizontal;
Grid.SetRow(myStackPanel, 1);
Image myImage4 = new Image();
BitmapImage bi4 = new BitmapImage();
bi4.BeginInit();
bi4.UriSource = new Uri("smiley_stackpanel.png", UriKind.Relative);
bi4.EndInit();
myImage4.Source = bi4;
Image myImage5 = new Image();
BitmapImage bi5 = new BitmapImage();
bi5.BeginInit();
bi5.UriSource = new Uri("smiley_stackpanel.png", UriKind.Relative);
bi5.EndInit();
myImage5.Source = bi5;
Image myImage6 = new Image();
BitmapImage bi6 = new BitmapImage();
bi6.BeginInit();
bi6.UriSource = new Uri("smiley_stackpanel.PNG", UriKind.Relative);
bi6.EndInit();
myImage6.Stretch = Stretch.Fill;
myImage6.Source = bi6;
// Add the images to the parent StackPanel
myStackPanel.Children.Add(myImage4);
myStackPanel.Children.Add(myImage5);
myStackPanel.Children.Add(myImage6);
// Add the layout panels as children of the Grid
myGrid.Children.Add(myDockPanel);
myGrid.Children.Add(myStackPanel);
// Add the Grid as the Content of the Parent Window Object
mainWindow.Content = myGrid;
mainWindow.Show ();
<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="StackPanel vs. DockPanel">
<Grid Width="175" Height="150">
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<DockPanel Grid.Column="0" Grid.Row="0">
<Image Source="smiley_stackpanel.png" />
<Image Source="smiley_stackpanel.png" />
<Image Source="smiley_stackpanel.png" Stretch="Fill"/>
</DockPanel>
<StackPanel Grid.Column="0" Grid.Row="1" Orientation="Horizontal">
<Image Source="smiley_stackpanel.png" />
<Image Source="smiley_stackpanel.png" />
<Image Source="smiley_stackpanel.png" Stretch="Fill"/>
</StackPanel>
</Grid>
</Page>
下圖顯示呈現行為的差異。
定義和使用 StackPanel
下列範例會示範如何使用 StackPanel 建立一組垂直放置的按鈕。至於水平放置,請將 Orientation 屬性設為 Horizontal。
WindowTitle = "StackPanel Sample"
' Define the StackPanel
Dim myStackPanel As New StackPanel()
myStackPanel.HorizontalAlignment = Windows.HorizontalAlignment.Left
myStackPanel.VerticalAlignment = Windows.VerticalAlignment.Top
' Define child content
Dim myButton1 As New Button()
myButton1.Content = "Button 1"
Dim myButton2 As New Button()
myButton2.Content = "Button 2"
Dim myButton3 As New Button()
myButton3.Content = "Button 3"
' Add child elements to the parent StackPanel
myStackPanel.Children.Add(myButton1)
myStackPanel.Children.Add(myButton2)
myStackPanel.Children.Add(myButton3)
Me.Content = myStackPanel
// Create the application's main window
mainWindow = new Window ();
mainWindow.Title = "StackPanel Sample";
// Define the StackPanel
myStackPanel = new StackPanel();
myStackPanel.HorizontalAlignment = HorizontalAlignment.Left;
myStackPanel.VerticalAlignment = VerticalAlignment.Top;
// Define child content
Button myButton1 = new Button();
myButton1.Content = "Button 1";
Button myButton2 = new Button();
myButton2.Content = "Button 2";
Button myButton3 = new Button();
myButton3.Content = "Button 3";
// Add child elements to the parent StackPanel
myStackPanel.Children.Add(myButton1);
myStackPanel.Children.Add(myButton2);
myStackPanel.Children.Add(myButton3);
// Add the StackPanel as the Content of the Parent Window Object
mainWindow.Content = myStackPanel;
mainWindow.Show ();
<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" WindowTitle="StackPanel Sample">
<StackPanel HorizontalAlignment="Left"
VerticalAlignment="Top">
<Button>Button 1</Button>
<Button>Button 2</Button>
<Button>Button 3</Button>
</StackPanel>
</Page>
完成編譯的應用程式會產生新的 UI,如下所示。
VirtualizingStackPanel
WPF 也提供另一種 StackPanel 項目,這種項目會自動「虛擬化」資料繫結子內容。在此情況下,「虛擬化」一詞是指一種技術,這種技術可以依據畫面上所顯示的項目,從眾多資料項目當中產生 UIElement 項目的子集。在指定時間畫面上只會出現少數項目時,產生大量 UI 項目會耗用許多記憶體和處理器資源。VirtualizingStackPanel (透過 VirtualizingPanel 所提供的功能) 會計算可見項目,並從 ItemsControl (例如 ListBox 或 ListView) 搭配 ItemContainerGenerator 使用,只為可見的項目建立 UIElement。
VirtualizingStackPanel 項目會自動設為 ListBox 等控制項的主項目。裝載資料繫結集合時,內容只要位於 ScrollViewer 的邊界內,就會自動進行虛擬化。如此可在裝載許多子項目時大幅提升效能。
下列標記示範如何將 VirtualizingStackPanel 做為主項目。IsVirtualizing 附加屬性必須設為 True (預設值),才能進行虛擬化。
<StackPanel DataContext="{Binding Source={StaticResource Leagues}}">
<TextBlock Text="{Binding XPath=@name}" FontFamily="Arial" FontSize="18" Foreground="Black"/>
<ListBox VirtualizingStackPanel.IsVirtualizing="True"
ItemsSource="{Binding XPath=Team}"
ItemTemplate="{DynamicResource NameDataStyle}"/>
</StackPanel>
WrapPanel
WrapPanel 可用以將子項目從左到右依序放置,並在內容到達父容器的邊緣時將其換到下一行。內容可以水平或垂直排列。WrapPanel 適用於簡單的非固定使用者介面 (UI) 案例。也可用以對其所有子項目套用統一的大小。
下列範例會示範如何建立 WrapPanel,以顯示會在到達其容器邊緣時換行的 Button 控制項。
WindowTitle = "WrapPanel Sample"
' Instantiate a new WrapPanel and set properties
Dim myWrapPanel As New WrapPanel()
myWrapPanel.Background = Brushes.Azure
myWrapPanel.Orientation = Orientation.Horizontal
myWrapPanel.ItemHeight = 25
myWrapPanel.ItemWidth = 75
myWrapPanel.Width = 150
myWrapPanel.HorizontalAlignment = Windows.HorizontalAlignment.Left
myWrapPanel.VerticalAlignment = Windows.VerticalAlignment.Top
' Define 3 button elements. Each button is sized at width of 75, so the third button wraps to the next line.
Dim btn1 As New Button()
btn1.Content = "Button 1"
Dim btn2 As New Button()
btn2.Content = "Button 2"
Dim btn3 As New Button()
btn3.Content = "Button 3"
' Add the buttons to the parent WrapPanel using the Children.Add method.
myWrapPanel.Children.Add(btn1)
myWrapPanel.Children.Add(btn2)
myWrapPanel.Children.Add(btn3)
' Add the WrapPanel to the Page as Content
Me.Content = myWrapPanel
// Create the application's main window
mainWindow = new System.Windows.Window();
mainWindow.Title = "WrapPanel Sample";
// Instantiate a new WrapPanel and set properties
myWrapPanel = new WrapPanel();
myWrapPanel.Background = System.Windows.Media.Brushes.Azure;
myWrapPanel.Orientation = Orientation.Horizontal;
myWrapPanel.ItemHeight = 25;
myWrapPanel.ItemWidth = 75;
myWrapPanel.Width = 150;
myWrapPanel.HorizontalAlignment = HorizontalAlignment.Left;
myWrapPanel.VerticalAlignment = VerticalAlignment.Top;
// Define 3 button elements. Each button is sized at width of 75, so the third button wraps to the next line.
btn1 = new Button();
btn1.Content = "Button 1";
btn2 = new Button();
btn2.Content = "Button 2";
btn3 = new Button();
btn3.Content = "Button 3";
// Add the buttons to the parent WrapPanel using the Children.Add method.
myWrapPanel.Children.Add(btn1);
myWrapPanel.Children.Add(btn2);
myWrapPanel.Children.Add(btn3);
// Add the WrapPanel to the MainWindow as Content
mainWindow.Content = myWrapPanel;
mainWindow.Show();
<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" WindowTitle="WrapPanel Sample">
<Border HorizontalAlignment="Left" VerticalAlignment="Top" BorderBrush="Black" BorderThickness="2">
<WrapPanel Background="LightBlue" Width="200" Height="100">
<Button Width="200">Button 1</Button>
<Button>Button 2</Button>
<Button>Button 3</Button>
<Button>Button 4</Button>
</WrapPanel>
</Border>
</Page>
完成編譯的應用程式會產生新的 UI,如下所示。
巢狀面板項目
Panel 項目可彼此以巢狀方式放置,以產生複雜的配置。若有個 Panel 非常適用於部分 UI,但不符合 UI 其他部分的需求,這種配置方式會很實用。
應用程式可支援的巢狀數量並沒有實際限制,但一般而言,最好將應用程式限定為僅使用您所需配置真正需要的面板。在許多情況下,可以使用 Grid 項目來取代巢狀面板,因為該項目具有可做為配置容器的彈性。如此可將非必要的項目排除在樹狀結構外,而提升應用程式的效能。
下列範例會示範如何建立透過 Panel 項目完成特定配置的 UI。在此特殊情況下,DockPanel 項目用於提供 UI 結構,而 StackPanel 項目、Grid 與 Canvas 則用於將子項目精確地放置在父 DockPanel 內。
Dim myDockPanel As New DockPanel()
Dim myBorder2 As New Border()
myBorder2.BorderThickness = New Thickness(1)
myBorder2.BorderBrush = Brushes.Black
DockPanel.SetDock(myBorder2, Dock.Left)
Dim myStackPanel As New StackPanel()
Dim myButton1 As New Button()
myButton1.Content = "Left Docked"
myButton1.Margin = New Thickness(5)
Dim myButton2 As New Button()
myButton2.Content = "StackPanel"
myButton2.Margin = New Thickness(5)
myStackPanel.Children.Add(myButton1)
myStackPanel.Children.Add(myButton2)
myBorder2.Child = myStackPanel
Dim myBorder3 As New Border()
myBorder3.BorderThickness = New Thickness(1)
myBorder3.BorderBrush = Brushes.Black
DockPanel.SetDock(myBorder3, Dock.Top)
Dim myGrid As New Grid()
myGrid.ShowGridLines = True
Dim myRowDef1 As New RowDefinition()
Dim myRowDef2 As New RowDefinition()
Dim myColDef1 As New ColumnDefinition()
Dim myColDef2 As New ColumnDefinition()
Dim myColDef3 As New ColumnDefinition()
myGrid.ColumnDefinitions.Add(myColDef1)
myGrid.ColumnDefinitions.Add(myColDef2)
myGrid.ColumnDefinitions.Add(myColDef3)
myGrid.RowDefinitions.Add(myRowDef1)
myGrid.RowDefinitions.Add(myRowDef2)
Dim myTextBlock1 As New TextBlock()
myTextBlock1.FontSize = 20
myTextBlock1.Margin = New Thickness(10)
myTextBlock1.Text = "Grid Element Docked at the Top"
Grid.SetRow(myTextBlock1, 0)
Grid.SetColumnSpan(myTextBlock1, 3)
Dim myButton3 As New Button()
myButton3.Margin = New Thickness(5)
myButton3.Content = "A Row"
Grid.SetColumn(myButton3, 0)
Grid.SetRow(myButton3, 1)
Dim myButton4 As New Button()
myButton4.Margin = New Thickness(5)
myButton4.Content = "of Button"
Grid.SetColumn(myButton4, 1)
Grid.SetRow(myButton4, 1)
Dim myButton5 As New Button()
myButton5.Margin = New Thickness(5)
myButton5.Content = "Elements"
Grid.SetColumn(myButton5, 2)
Grid.SetRow(myButton5, 1)
myGrid.Children.Add(myTextBlock1)
myGrid.Children.Add(myButton3)
myGrid.Children.Add(myButton4)
myGrid.Children.Add(myButton5)
myBorder3.Child = myGrid
Dim myBorder4 As New Border()
myBorder4.BorderBrush = Brushes.Black
myBorder4.BorderThickness = New Thickness(1)
DockPanel.SetDock(myBorder4, Dock.Bottom)
Dim myStackPanel2 As New StackPanel()
myStackPanel2.Orientation = Orientation.Horizontal
Dim myTextBlock2 As New TextBlock()
myTextBlock2.Text = "This StackPanel is Docked to the Bottom"
myTextBlock2.Margin = New Thickness(5)
myStackPanel2.Children.Add(myTextBlock2)
myBorder4.Child = myStackPanel2
Dim myBorder5 As New Border()
myBorder5.BorderBrush = Brushes.Black
myBorder5.BorderThickness = New Thickness(1)
Dim myCanvas As New Canvas()
myCanvas.ClipToBounds = True
Dim myTextBlock3 As New TextBlock()
myTextBlock3.Text = "Content in the Canvas will Fill the remaining space."
Canvas.SetTop(myTextBlock3, 50)
Canvas.SetLeft(myTextBlock3, 50)
Dim myEllipse As New Ellipse()
myEllipse.Height = 100
myEllipse.Width = 125
myEllipse.Fill = Brushes.CornflowerBlue
myEllipse.Stroke = Brushes.Aqua
Canvas.SetTop(myEllipse, 100)
Canvas.SetLeft(myEllipse, 150)
myCanvas.Children.Add(myTextBlock3)
myCanvas.Children.Add(myEllipse)
myBorder5.Child = myCanvas
myDockPanel.Children.Add(myBorder2)
myDockPanel.Children.Add(myBorder3)
myDockPanel.Children.Add(myBorder4)
myDockPanel.Children.Add(myBorder5)
// Define the DockPanel.
myDockPanel = new DockPanel();
// Add the Left Docked StackPanel
Border myBorder2 = new Border();
myBorder2.BorderThickness = new Thickness(1);
myBorder2.BorderBrush = Brushes.Black;
DockPanel.SetDock(myBorder2, Dock.Left);
StackPanel myStackPanel = new StackPanel();
Button myButton1 = new Button();
myButton1.Content = "Left Docked";
myButton1.Margin = new Thickness(5);
Button myButton2 = new Button();
myButton2.Content = "StackPanel";
myButton2.Margin = new Thickness(5);
myStackPanel.Children.Add(myButton1);
myStackPanel.Children.Add(myButton2);
myBorder2.Child = myStackPanel;
// Add the Top Docked Grid.
Border myBorder3 = new Border();
myBorder3.BorderThickness = new Thickness(1);
myBorder3.BorderBrush = Brushes.Black;
DockPanel.SetDock(myBorder3, Dock.Top);
Grid myGrid = new Grid();
myGrid.ShowGridLines = true;
RowDefinition myRowDef1 = new RowDefinition();
RowDefinition myRowDef2 = new RowDefinition();
ColumnDefinition myColDef1 = new ColumnDefinition();
ColumnDefinition myColDef2 = new ColumnDefinition();
ColumnDefinition myColDef3 = new ColumnDefinition();
myGrid.ColumnDefinitions.Add(myColDef1);
myGrid.ColumnDefinitions.Add(myColDef2);
myGrid.ColumnDefinitions.Add(myColDef3);
myGrid.RowDefinitions.Add(myRowDef1);
myGrid.RowDefinitions.Add(myRowDef2);
TextBlock myTextBlock1 = new TextBlock();
myTextBlock1.FontSize = 20;
myTextBlock1.Margin = new Thickness(10);
myTextBlock1.Text = "Grid Element Docked at the Top";
Grid.SetRow(myTextBlock1, 0);
Grid.SetColumnSpan(myTextBlock1, 3);
Button myButton3 = new Button();
myButton3.Margin = new Thickness(5);
myButton3.Content = "A Row";
Grid.SetColumn(myButton3, 0);
Grid.SetRow(myButton3, 1);
Button myButton4 = new Button();
myButton4.Margin = new Thickness(5);
myButton4.Content = "of Button";
Grid.SetColumn(myButton4, 1);
Grid.SetRow(myButton4, 1);
Button myButton5 = new Button();
myButton5.Margin = new Thickness(5);
myButton5.Content = "Elements";
Grid.SetColumn(myButton5, 2);
Grid.SetRow(myButton5, 1);
myGrid.Children.Add(myTextBlock1);
myGrid.Children.Add(myButton3);
myGrid.Children.Add(myButton4);
myGrid.Children.Add(myButton5);
myBorder3.Child = myGrid;
// Add the Bottom Docked StackPanel.
Border myBorder4 = new Border();
myBorder4.BorderBrush = Brushes.Black;
myBorder4.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder4, Dock.Bottom);
StackPanel myStackPanel2 = new StackPanel();
myStackPanel2.Orientation = Orientation.Horizontal;
TextBlock myTextBlock2 = new TextBlock();
myTextBlock2.Text = "This StackPanel is Docked to the Bottom";
myTextBlock2.Margin = new Thickness(5);
myStackPanel2.Children.Add(myTextBlock2);
myBorder4.Child = myStackPanel2;
// Add the Canvas, that fills remaining space.
Border myBorder5 = new Border();
myBorder4.BorderBrush = Brushes.Black;
myBorder5.BorderThickness = new Thickness(1);
Canvas myCanvas = new Canvas();
myCanvas.ClipToBounds = true;
TextBlock myTextBlock3 = new TextBlock();
myTextBlock3.Text = "Content in the Canvas will Fill the remaining space.";
Canvas.SetTop(myTextBlock3, 50);
Canvas.SetLeft(myTextBlock3, 50);
Ellipse myEllipse = new Ellipse();
myEllipse.Height = 100;
myEllipse.Width = 125;
myEllipse.Fill = Brushes.CornflowerBlue;
myEllipse.Stroke = Brushes.Aqua;
Canvas.SetTop(myEllipse, 100);
Canvas.SetLeft(myEllipse, 150);
myCanvas.Children.Add(myTextBlock3);
myCanvas.Children.Add(myEllipse);
myBorder5.Child = myCanvas;
// Add child elements to the parent DockPanel.
myDockPanel.Children.Add(myBorder2);
myDockPanel.Children.Add(myBorder3);
myDockPanel.Children.Add(myBorder4);
myDockPanel.Children.Add(myBorder5);
<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" WindowTitle="Nested Panels">
<Border Background="AliceBlue"
Width="400"
Height="300"
BorderBrush="DarkSlateBlue"
BorderThickness="2"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<DockPanel>
<Border BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Left">
<StackPanel>
<Button Margin="5">Left Docked</Button>
<Button Margin="5">StackPanel</Button>
</StackPanel>
</Border>
<Border BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Top">
<Grid ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock FontSize="20" Margin="10" Grid.ColumnSpan="3" Grid.Row="0">Grid Element Docked to the Top.</TextBlock>
<Button Grid.Row="1" Grid.Column="0" Margin="5">A Row</Button>
<Button Grid.Row="1" Grid.Column="1" Margin="5">of Button</Button>
<Button Grid.Row="1" Grid.Column="2" Margin="5">Elements</Button>
</Grid>
</Border>
<Border BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Bottom">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="5">This StackPanel is Docked to the Bottom.</TextBlock>
</StackPanel>
</Border>
<Border BorderBrush="Black" BorderThickness="1">
<Canvas ClipToBounds="True">
<TextBlock Canvas.Top="50" Canvas.Left="50">
Content in the Canvas will Fill the remaining Space.
</TextBlock>
<Ellipse Height="100" Width="125" Fill="CornflowerBlue" Stroke="Aqua" Canvas.Top="100" Canvas.Left="150"/>
</Canvas>
</Border>
</DockPanel>
</Border>
</Page>
完成編譯的應用程式會產生新的 UI,如下所示。
自訂面板項目
雖然 WPF 提供了許多富有彈性的配置控制項,但您也可以覆寫 ArrangeOverride 與 MeasureOverride 方法,以進行自訂配置行為。自訂縮放與定位可藉由在覆寫方法內定義新的定位行為完成。
同樣地,您也可以覆寫 ArrangeOverride 與 MeasureOverride 方法,而根據衍生類別 (如 Canvas 或 Grid) 定義自訂配置行為。
下列標記示範如何使用 C# 建立自訂 Panel 項目。這項新的 Panel (定義為 PlotPanel) 支援利用硬式編碼的 x 和 y 座標進行子項目的定位。在此範例中,Rectangle 項目 (未顯示) 會定位於描繪點 50 (x) 與 50 (y)。
Public Class PlotPanel
Inherits Panel
'Override the default Measure method of Panel.
Protected Overrides Function MeasureOverride(ByVal availableSize As System.Windows.Size) As System.Windows.Size
Dim childSize As Size = CType(availableSize, Size)
For Each child As UIElement In InternalChildren
child.Measure(childSize)
Next
Return MyBase.MeasureOverride(availableSize)
End Function
Protected Overrides Function ArrangeOverride(ByVal finalSize As System.Windows.Size) As System.Windows.Size
For Each child As UIElement In InternalChildren
Dim x As Double = 50
Dim y As Double = 50
child.Arrange(New Rect(New System.Windows.Point(x, y), child.DesiredSize))
Next
Return MyBase.ArrangeOverride(finalSize)
End Function
End Class
public class PlotPanel : Panel
{
// Default public constructor
public PlotPanel()
: base()
{
}
// Override the default Measure method of Panel
protected override Size MeasureOverride(Size availableSize)
{
Size panelDesiredSize = new Size();
// In our example, we just have one child.
// Report that our panel requires just the size of its only child.
foreach (UIElement child in InternalChildren)
{
child.Measure(availableSize);
panelDesiredSize = child.DesiredSize;
}
return panelDesiredSize ;
}
protected override Size ArrangeOverride(Size finalSize)
{
foreach (UIElement child in InternalChildren)
{
double x = 50;
double y = 50;
child.Arrange(new Rect(new Point(x, y), child.DesiredSize));
}
return finalSize; // Returns the final Arranged size
}
}
若要檢視完整的範例,請參閱建立簡單自訂面板範例。
若要檢視較複雜的自訂面板實作,請參閱建立自訂內容換行面板範例。
當地語系化/全球化支援
WPF 支援多項有助於建立可當地語系化之 UI 的功能。
所有面板項目原本即支援 FlowDirection 屬性,此屬性可根據使用者的地區設定或語言設定,以動態方式重新排列內容。如需詳細資訊,請參閱FlowDirection。
SizeToContent 屬性可提供適當機制,讓應用程式開發人員能夠預測當地語系化 UI 的需求。使用此屬性的 WidthAndHeight 值時,父 Window 一律會動態調整大小以符合內容,而不受人工高度或寬度的限制。
DockPanel、Grid 與 StackPanel 都很適用於可當地語系化的 UI。Canvas 則不是很好的選擇,因為它會以絕對的方式放置內容,而難以進行當地語系化。
如需建立含可當地語系化使用者介面 (UI) 之 WPF 應用程式的其他資訊,請參閱使用自動配置概觀。