面板概觀
Panel (部分機器翻譯) 元素是控制元素呈現的元件,即其大小和維度、其位置,以及其子內容的排列方式。 Windows Presentation Foundation (WPF) 提供一些預先定義的 Panel (部分機器翻譯) 元素,以及建構自訂 Panel (部分機器翻譯) 元素的能力。
本主題包含下列各節。
面板類別
Panel (部分機器翻譯) 是可在 Windows Presentation Foundation (WPF) 中提供版面配置支援之所有元素的基底類別。 衍生的 Panel (部分機器翻譯) 元素可在 Extensible Application Markup Language (XAML) 和程式碼中用來置放及排列元素。
WPF 包含一套完整的衍生面板實作,可讓您設計許多複雜的版面配置。 這些衍生類別會公開可促成大多數標準使用者介面 (UI) 案例的屬性和方法。 找不到符合自身需求之子排列行為的開發人員,可以透過覆寫 ArrangeOverride (英文) 和 MeasureOverride (英文) 方法來建立新的版面配置。 如需有關自訂版面配置行為的詳細資訊,請參閱自訂面板元素。
面板的一般成員
所有 Panel (部分機器翻譯) 元素都支援 FrameworkElement (部分機器翻譯) 所定義的基底調整大小和置放屬性,包括 Height (部分機器翻譯)、Width (部分機器翻譯)、HorizontalAlignment (英文)、VerticalAlignment (英文)、Margin (部分機器翻譯) 和 LayoutTransform (部分機器翻譯)。 如需 FrameworkElement (部分機器翻譯) 所定義置放屬性的其他資訊,請參閱對齊、邊界和填補概觀。
Panel (部分機器翻譯) 會公開對了解及使用版面配置而言非常重要的其他屬性。 Background (部分機器翻譯) 屬性可用來以 Brush (部分機器翻譯) 填滿衍生面板元素界限之間的區域。 Children (英文) 代表由 Panel (部分機器翻譯) 所組成元素的子集合。 InternalChildren (部分機器翻譯) 代表 Children (英文) 集合的內容,加上資料繫結所產生的成員。 這兩者都包含父 Panel (部分機器翻譯) 內所裝載之子元素的 UIElementCollection (部分機器翻譯)。
Panel 也會公開 Panel.ZIndex (英文) 附加屬性,可用來在衍生的 Panel (部分機器翻譯) 中達到分層順序。 Panel.ZIndex (部分機器翻譯) 值較高之面板 Children (英文) 集合的成員會出現在 Panel.ZIndex (部分機器翻譯) 值較低的集合前面。 這對於 Canvas (部分機器翻譯) 和 Grid (部分機器翻譯) 等面板特別有用,可讓子元素共用相同的座標空間。
Panel (部分機器翻譯) 也會定義 OnRender (英文) 方法,可用來覆寫 Panel (部分機器翻譯) 的預設展示行為。
附加屬性
衍生的面板元素廣泛運用了附加屬性。 附加屬性是相依性屬性的特殊形式,不具傳統的通用語言執行平台 (CLR) 屬性「包裝函式」。 附加屬性在 Extensible Application Markup Language (XAML) 中有特殊語法,可在接下來的數個範例中看到。
附加屬性的其中一個用途是要允許子元素儲存父元素實際定義之屬性的唯一值。 此功能的應用之一是讓子元素通知父元素其希望如何在使用者介面 (UI) 中呈現,這對應用程式版面配置而言極為有用。 如需詳細資訊,請參閱附加屬性概觀。
衍生的面板元素
許多物件都衍生自 Panel (部分機器翻譯),但並非全都要用來作為根版面配置提供者。 有六個定義的面板類別 (Canvas (部分機器翻譯)、DockPanel (部分機器翻譯)、Grid (部分機器翻譯)、StackPanel (部分機器翻譯)、VirtualizingStackPanel (部分機器翻譯) 和 WrapPanel (部分機器翻譯)) 是專為建立應用程式 UI 而設計。
每個面板元素都會封裝自己的特殊功能,如下表所示。
元素名稱 | UI 面板? | 描述 |
---|---|---|
Canvas | Yes | 使用 Canvas (部分機器翻譯) 區域的相對座標,定義可明確置放子元素的區域。 |
DockPanel | Yes | 定義一個區域,可供您在其中以子元素彼此間相對的水平或垂直方式排列子元素。 |
Grid | Yes | 定義由資料行與資料列組成的彈性方格區域。 Grid (部分機器翻譯) 的子元素可以使用 Margin (部分機器翻譯) 屬性精確地置放。 |
StackPanel | Yes | 將子元素排成單一行,以水平或垂直方式排列。 |
TabPanel | No | 在 TabControl (部分機器翻譯) 中,處理索引標籤按鈕的版面配置。 |
ToolBarOverflowPanel | No | 在 ToolBar (部分機器翻譯) 控制項中排列內容。 |
UniformGrid | No | UniformGrid (部分機器翻譯) 可用來在所有儲存格大小相等的方格中排列子元素。 |
VirtualizingPanel | No | 為面板提供一個可將其子集合「虛擬化」的基底類別。 |
VirtualizingStackPanel | Yes | 將內容以單行水平方向或垂直方向來排列並虛擬化。 |
WrapPanel | Yes | WrapPanel (部分機器翻譯) 會將子元素置放於由左至右的連續位置,在包含方塊的邊緣將內容換至下一行。 後續順序會依序由上而下或由左而右進行,需視 Orientation (英文) 屬性的值而定。 |
使用者介面面板
WPF 中有六個可用面板類別,已最佳化來支援 UI 案例:Canvas (部分機器翻譯)、DockPanel (部分機器翻譯)、Grid (部分機器翻譯)、StackPanel (部分機器翻譯)、VirtualizingStackPanel (部分機器翻譯) 和 WrapPanel (部分機器翻譯)。 這些面板元素相當容易使用、多樣化且可延伸,足以滿足大多數應用程式的需求。
每個衍生的 Panel (部分機器翻譯) 元素都會以不同的方式處理調整大小條件約束。 了解 Panel (部分機器翻譯) 如何處理條件約束 (不論是水平方向還是垂直方向) 可讓您更容易預測版面配置情況。
面板名稱 | x 維度 | y 維度 |
---|---|---|
Canvas | 受內容限制 | 受內容限制 |
DockPanel | 受限 | 受限 |
StackPanel (部分機器翻譯) (垂直方向) | 受限 | 受內容限制 |
StackPanel (部分機器翻譯) (水平方向) | 受內容限制 | 受限 |
Grid | 受限 | 受限,但在 Auto (英文) 套用到列與欄的情況下除外 |
WrapPanel | 受內容限制 | 受內容限制 |
如需這些元素中每個元素的詳細描述和使用方式範例,請參閱下方。
Canvas \(英文\)
Canvas (部分機器翻譯) 元素可讓您根據絕對 x 和 y 座標來置放內容。 元素的繪製位置可以是一個唯一的位置;或者,如果元素佔據相同的座標,則它們在標記中的出現順序會決定元素的繪製順序。
Canvas (部分機器翻譯) 提供任何 Panel (部分機器翻譯) 最具彈性的版面配置支援。 Height 和 Width 屬性可用來定義畫布的區域,而其中的元素會獲指派相對於父 Canvas (部分機器翻譯) 區域的絕對座標。 有四個附加屬性 (Canvas.Left (英文)、Canvas.Top (英文)、Canvas.Right (部分機器翻譯) 和 Canvas.Bottom (英文)) 能夠在 Canvas (部分機器翻譯) 中精細控制物件位置,讓開發人員能夠精確置放和排列螢幕上的元素。
畫布內的 ClipToBounds
Canvas (部分機器翻譯) 可將子元素置放於螢幕上的任何位置,即使是已超出其自己定義的 Height (部分機器翻譯) 和 Width (部分機器翻譯) 的座標上也可以。 此外,Canvas (部分機器翻譯) 不會受到其子元素的大小所影響。 因此,子元素可能會在超出父 Canvas (部分機器翻譯) 周框方塊的位置過度繪製其他元素。 Canvas (部分機器翻譯) 的預設行為是允許在超出父 Canvas (部分機器翻譯) 界限的位置繪製子元素。 如果不需要此行為,可將 ClipToBounds (部分機器翻譯) 屬性設定為 true
。 這將導致 Canvas (部分機器翻譯) 裁剪成其自身大小。 Canvas (部分機器翻譯) 是唯一允許在超出其範圍的位置繪製子元素的版面配置元素。
在寬度屬性比較範例中有此行為的圖例解說。
定義和使用 Canvas
只要使用 Extensible Application Markup Language (XAML) 或程式碼,即可將 Canvas (部分機器翻譯) 具現化。 下列範例示範如何使用 Canvas (部分機器翻譯),以絕對方式置放內容。 此程式碼會產生三個 100 像素的方形。 第一個方形為紅色,其左上角 (x, y) 位置是指定為 (0, 0)。 第二個方形為綠色,其左上角位置是 (100, 100),正好是在第一個方形的右下方。 第三個方形為藍色,其左上角位置是 (50, 50),因此包含第一個方形的右下象限,以及第二個方形的左上象限。 由於第三個方形是最後放置的,因此它會顯示在另外兩個方形上方,也就是說,重疊部分會呈現第三個方塊的顏色。
// 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 ();
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
<Page WindowTitle="Canvas Sample" xmlns="http://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。
典型的 Canvas 元素。panel_intro_canvas
DockPanel
DockPanel (部分機器翻譯) 元素會使用 DockPanel.Dock (部分機器翻譯) 附加屬性,如子內容元素中所設定,沿著容器邊緣置放內容。 當 DockPanel.Dock (部分機器翻譯) 設定為 Top (部分機器翻譯) 或 Bottom (部分機器翻譯) 時,其會將子元素置放在彼此的上方或下方。 當 DockPanel.Dock (部分機器翻譯) 設定為 Left (部分機器翻譯) 或 Right (部分機器翻譯) 時,其會將子元素置放在彼此的左邊或右邊。 LastChildFill (英文) 屬性會決定新增為 DockPanel (部分機器翻譯) 子元素之最終元素的位置。
您可以使用 DockPanel (部分機器翻譯) 來置放一組相關的控制項,例如一組按鈕。 或者,您也可以使用它來建立「有窗格的」UI,類似於 Microsoft Outlook 中的 UI。
依內容調整大小
如果未指定其 Height (部分機器翻譯) 和 Width (部分機器翻譯) 屬性,DockPanel (部分機器翻譯) 就會根據其內容調整大小。 大小可以因應其子元素的大小來增加或縮減。 不過,若已指定這些屬性且沒有其他空間可供下一個指定的子元素使用,DockPanel (部分機器翻譯) 便不會顯示該子元素或後續的子元素,也不會測量後續的子元素。
LastChildFill
根據預設,DockPanel (部分機器翻譯) 元素的最後一個子元素將會「填滿」其餘未配置的空間。 如果不需要此行為,請將 LastChildFill (英文) 屬性設定為 false
。
定義和使用 DockPanel
下列範例示範如何使用 DockPanel (部分機器翻譯) 來分割空間。 有五個 Border (部分機器翻譯) 元素會新增為父 DockPanel (部分機器翻譯) 的子元素。 每個都使用不同的 DockPanel (部分機器翻譯) 置放屬性來分割空間。 最後的元素會「填滿」剩餘的未配置空間。
// Create the application's main window
mainWindow = gcnew Window();
mainWindow->Title = "DockPanel Sample";
// Create the DockPanel
DockPanel^ myDockPanel = gcnew DockPanel();
myDockPanel->LastChildFill = true;
// Define the child content
Border^ myBorder1 = gcnew Border();
myBorder1->Height = 25;
myBorder1->Background = Brushes::SkyBlue;
myBorder1->BorderBrush = Brushes::Black;
myBorder1->BorderThickness = Thickness(1);
DockPanel::SetDock(myBorder1, Dock::Top);
TextBlock^ myTextBlock1 = gcnew TextBlock();
myTextBlock1->Foreground = Brushes::Black;
myTextBlock1->Text = "Dock = Top";
myBorder1->Child = myTextBlock1;
Border^ myBorder2 = gcnew Border();
myBorder2->Height = 25;
myBorder2->Background = Brushes::SkyBlue;
myBorder2->BorderBrush = Brushes::Black;
myBorder2->BorderThickness = Thickness(1);
DockPanel::SetDock(myBorder2, Dock::Top);
TextBlock^ myTextBlock2 = gcnew TextBlock();
myTextBlock2->Foreground = Brushes::Black;
myTextBlock2->Text = "Dock = Top";
myBorder2->Child = myTextBlock2;
Border^ myBorder3 = gcnew Border();
myBorder3->Height = 25;
myBorder3->Background = Brushes::LemonChiffon;
myBorder3->BorderBrush = Brushes::Black;
myBorder3->BorderThickness = Thickness(1);
DockPanel::SetDock(myBorder3, Dock::Bottom);
TextBlock^ myTextBlock3 = gcnew TextBlock();
myTextBlock3->Foreground = Brushes::Black;
myTextBlock3->Text = "Dock = Bottom";
myBorder3->Child = myTextBlock3;
Border^ myBorder4 = gcnew Border();
myBorder4->Width = 200;
myBorder4->Background = Brushes::PaleGreen;
myBorder4->BorderBrush = Brushes::Black;
myBorder4->BorderThickness = Thickness(1);
DockPanel::SetDock(myBorder4, Dock::Left);
TextBlock^ myTextBlock4 = gcnew TextBlock();
myTextBlock4->Foreground = Brushes::Black;
myTextBlock4->Text = "Dock = Left";
myBorder4->Child = myTextBlock4;
Border^ myBorder5 = gcnew Border();
myBorder5->Background = Brushes::White;
myBorder5->BorderBrush = Brushes::Black;
myBorder5->BorderThickness = Thickness(1);
TextBlock^ myTextBlock5 = gcnew 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();
// 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 ();
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
<Page xmlns="http://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。
典型的 DockPanel 案例。panel_intro_dockpanel
方格
Grid (部分機器翻譯) 元素合併了絕對位置與表格式資料控制項的功能。 Grid (部分機器翻譯) 可讓您輕鬆地置放元素並設定樣式。 Grid (部分機器翻譯) 可讓您定義彈性的列與欄群組,甚至提供可在多個 Grid (部分機器翻譯) 元素之間共用調整大小資訊的機制。
Grid 和 Table 有何不同
Table (部分機器翻譯) 和 Grid (部分機器翻譯) 會共用一些常見功能,但各自最適合用於不同的案例。 Table (部分機器翻譯) 專為在非固定格式文件中使用而設計 (如需非固定格式內容的詳細資訊,請參閱非固定格式文件概觀)。 方格最適合在表單內 (基本上,是在非固定格式內容以外的任何地方) 使用。 在 FlowDocument (部分機器翻譯) 中,Table (部分機器翻譯) 支援非固定格式內容行為,例如分頁、欄自動重排和內容選取範圍,而 Grid (部分機器翻譯) 則不支援。 另一方面,最好在 FlowDocument (部分機器翻譯) 之外使用 Grid (部分機器翻譯),原因很多,包括 Grid (部分機器翻譯) 是依據列和欄索引來新增元素,而 Table (部分機器翻譯) 則不是。 Grid (部分機器翻譯) 元素允許將子內容分層,這樣可讓多個元素存在於單一「儲存格」中,而 Table (部分機器翻譯) 不支援分層。 Grid (部分機器翻譯) 的子元素可相對於其「儲存格」界限區域,進行絕對置放。 Table (部分機器翻譯) 則不支援此功能。 最後,Grid (部分機器翻譯) 的粗細會比 Table (部分機器翻譯) 還淺。
資料行和資料列的調整大小行為
在 Grid (部分機器翻譯) 中定義的欄與列可利用 Star (英文) 調整大小,按比例分配剩餘的空間。 選取 Star (英文) 作為列或欄的 Height 或 Width 時,該欄或列會依加權比例獲得剩餘的可用空間。 這會與 Auto (英文) 形成對比,其將根據欄或列中內容的大小,平均分配空間。 使用 Extensible Application Markup Language (XAML) 時,會以 *
或 2*
表示此值。 在第一個案例中,資料列或資料行會獲得一倍的可用空間,在第二個案例中,則會獲得兩倍的可用空間,依此類推。 透過合併此技術,利用 Stretch
的 HorizontalAlignment (英文) 和 VerticalAlignment (部分機器翻譯) 值按比例分配空間,就能依螢幕空間的百分比來分割版面配置空間。 Grid (部分機器翻譯) 是唯一可以用這種方式分配空間的版面配置面板。
定義和使用 Grid
下列範例示範如何建置與 Windows [開始] 功能表中 [執行] 對話方塊上的 UI 類似的 UI。
// 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;
'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
編譯後的應用程式會產生一個看起來如下的新 UI。
典型的 Grid 元素。avalon_run_dialog
StackPanel \(英文\)
StackPanel (部分機器翻譯) 可讓您以指派的方向「堆疊」元素。 預設的堆疊方向為垂直。 Orientation (部分機器翻譯) 屬性可用來控制內容流程。
StackPanel 與DockPanel
雖然 DockPanel (部分機器翻譯) 也可「堆疊」子元素,但 DockPanel (部分機器翻譯) 和 StackPanel (部分機器翻譯) 在某些使用案例中不會產生類似的結果。 例如,子元素的順序可能影響其在 DockPanel (部分機器翻譯) 中的大小,但不會在 StackPanel (部分機器翻譯) 中產生影響。 這是因為 StackPanel (部分機器翻譯) 是以 PositiveInfinity (部分機器翻譯) 上的堆疊方向進行測量,而 DockPanel (部分機器翻譯) 只會測量可用的大小。
下列範例示範這項主要的差異。
// Create the application's main window
mainWindow = gcnew Window();
mainWindow->Title = "StackPanel vs. DockPanel";
// Add root Grid
myGrid = gcnew Grid();
myGrid->Width = 175;
myGrid->Height = 150;
RowDefinition^ myRowDef1 = gcnew RowDefinition();
RowDefinition^ myRowDef2 = gcnew RowDefinition();
myGrid->RowDefinitions->Add(myRowDef1);
myGrid->RowDefinitions->Add(myRowDef2);
// Define the DockPanel
myDockPanel = gcnew DockPanel();
Grid::SetRow(myDockPanel, 0);
//Define an Image and Source
Image^ myImage = gcnew Image();
BitmapImage^ bi = gcnew BitmapImage();
bi->BeginInit();
bi->UriSource = gcnew System::Uri("smiley_stackpanel.png", UriKind::Relative);
bi->EndInit();
myImage->Source = bi;
Image^ myImage2 = gcnew Image();
BitmapImage^ bi2 = gcnew BitmapImage();
bi2->BeginInit();
bi2->UriSource = gcnew System::Uri("smiley_stackpanel.png", UriKind::Relative);
bi2->EndInit();
myImage2->Source = bi2;
Image^ myImage3 = gcnew Image();
BitmapImage^ bi3 = gcnew BitmapImage();
bi3->BeginInit();
bi3->UriSource = gcnew System::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 = gcnew StackPanel();
myStackPanel->Orientation = Orientation::Horizontal;
Grid::SetRow(myStackPanel, 1);
Image^ myImage4 = gcnew Image();
BitmapImage^ bi4 = gcnew BitmapImage();
bi4->BeginInit();
bi4->UriSource = gcnew System::Uri("smiley_stackpanel.png", UriKind::Relative);
bi4->EndInit();
myImage4->Source = bi4;
Image^ myImage5 = gcnew Image();
BitmapImage^ bi5 = gcnew BitmapImage();
bi5->BeginInit();
bi5->UriSource = gcnew System::Uri("smiley_stackpanel.png", UriKind::Relative);
bi5->EndInit();
myImage5->Source = bi5;
Image^ myImage6 = gcnew Image();
BitmapImage^ bi6 = gcnew BitmapImage();
bi6->BeginInit();
bi6->UriSource = gcnew System::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();
// 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 ();
'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)
<Page xmlns="http://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 與DockPanel 螢幕擷取畫面layout_smiley_stackpanel
定義和使用 StackPanel
下列範例示範如何使用 StackPanel (部分機器翻譯) 建立一組垂直置放的按鈕。 針對水平置放,請將 Orientation (部分機器翻譯) 屬性設定為 Horizontal (英文)。
// 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 ();
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
編譯後的應用程式會產生一個看起來如下的新 UI。
典型的 StackPanel 元素。panel_intro_stackpanel
VirtualizingStackPanel
WPF 也會提供 StackPanel (部分機器翻譯) 元素的變化,可將資料繫結子內容自動「虛擬化」。 在此內容中,「虛擬化」一字係指一種技術,藉由這種技術,將可從較大量的資料項目,根據畫面上可見的項目來產生元素子集。 當在指定的時間內畫面上只能有幾個 UI 元素時,不論是就記憶體還是處理器而言,產生大量 UI 元素都會相當耗費資源。 VirtualizingStackPanel (部分機器翻譯) (透過 VirtualizingPanel (部分機器翻譯) 所提供的功能) 會計算可見項目,並使用 ItemsControl (部分機器翻譯) 的 ItemContainerGenerator (部分機器翻譯) (例如 ListBox (部分機器翻譯) 或 ListView (部分機器翻譯)),只針對可見項目建立元素。
VirtualizingStackPanel (部分機器翻譯) 元素會自動設定為控制項的項目主控件,例如 ListBox (部分機器翻譯)。 裝載資料繫結集合時,內容只要是位於 ScrollViewer (部分機器翻譯) 的範圍內,就會自動虛擬化。 當裝載許多子項目時,這可大幅改善效能。
下列標記示範如何使用 VirtualizingStackPanel (部分機器翻譯) 作為項目主控件。 VirtualizingStackPanel.IsVirtualizingProperty (部分機器翻譯) 附加屬性必須設定為 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 (部分機器翻譯) 控制項,以在其觸及容器邊緣時換行。
// Create the application's main window
mainWindow = gcnew System::Windows::Window();
mainWindow->Title = "WrapPanel Sample";
// Instantiate a new WrapPanel and set properties
myWrapPanel = gcnew WrapPanel();
myWrapPanel->Background = 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 = gcnew Button();
btn1->Content = "Button 1";
btn2 = gcnew Button();
btn2->Content = "Button 2";
btn3 = gcnew 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();
// 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.Width = 200;
myWrapPanel.HorizontalAlignment = HorizontalAlignment.Left;
myWrapPanel.VerticalAlignment = VerticalAlignment.Top;
// Define 3 button elements. The last three buttons are sized at width
// of 75, so the forth button wraps to the next line.
btn1 = new Button();
btn1.Content = "Button 1";
btn1.Width = 200;
btn2 = new Button();
btn2.Content = "Button 2";
btn2.Width = 75;
btn3 = new Button();
btn3.Content = "Button 3";
btn3.Width = 75;
btn4 = new Button();
btn4.Content = "Button 4";
btn4.Width = 75;
// Add the buttons to the parent WrapPanel using the Children.Add method.
myWrapPanel.Children.Add(btn1);
myWrapPanel.Children.Add(btn2);
myWrapPanel.Children.Add(btn3);
myWrapPanel.Children.Add(btn4);
// Add the WrapPanel to the MainWindow as Content
mainWindow.Content = myWrapPanel;
mainWindow.Show();
WindowTitle = "WrapPanel Sample"
' Instantiate a new WrapPanel and set properties
Dim myWrapPanel As New WrapPanel()
myWrapPanel.Background = Brushes.Azure
myWrapPanel.Orientation = Orientation.Horizontal
myWrapPanel.Width = 200
myWrapPanel.HorizontalAlignment = Windows.HorizontalAlignment.Left
myWrapPanel.VerticalAlignment = Windows.VerticalAlignment.Top
' Define 3 button elements. The last three buttons are sized at width
' of 75, so the forth button wraps to the next line.
Dim btn1 As New Button()
btn1.Content = "Button 1"
btn1.Width = 200
Dim btn2 As New Button()
btn2.Content = "Button 2"
btn2.Width = 75
Dim btn3 As New Button()
btn3.Content = "Button 3"
btn3.Width = 75
Dim btn4 As New Button()
btn4.Content = "Button 4"
btn4.Width = 75
' Add the buttons to the parent WrapPanel using the Children.Add method.
myWrapPanel.Children.Add(btn1)
myWrapPanel.Children.Add(btn2)
myWrapPanel.Children.Add(btn3)
myWrapPanel.Children.Add(btn4)
' Add the WrapPanel to the Page as Content
Me.Content = myWrapPanel
<Page xmlns="http://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。
典型的 WrapPanel 元素。WrapPanel_Element
巢狀面板元素
Panel (部分機器翻譯) 元素可以位於彼此的巢狀結構內,以產生複雜的版面配置。 這可證明在一個 Panel (部分機器翻譯) 非常適合 UI 的一部分,但可能不符合 UI 不同部分需求的情況下非常有用。
針對您應用程式可支援的巢狀結構數量並沒有特定的限制,不過,通常最好是讓您應用程式僅限使用對您所需版面配置而言實際必要的面板。 在許多情況下,您都可以使用 Grid (部分機器翻譯) 元素來代替巢狀面板,因其具有可作為版面配置容器的彈性。 這可以將不必要的元素排除在樹狀結構之外,以提升應用程式中的效能。
下列範例示範如何建立採用巢狀 Panel (部分機器翻譯) 元素的 UI,以實現特定的版面配置。 在此特定案例中,DockPanel (部分機器翻譯) 元素可用來提供 UI 結構,而巢狀 StackPanel (部分機器翻譯) 元素、Grid (部分機器翻譯) 和 Canvas (部分機器翻譯) 可用來將子元素精確置放於父 DockPanel (部分機器翻譯) 內。
// 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);
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)
編譯後的應用程式會產生一個看起來如下的新 UI。
採用巢狀面板的 UI。nested_panels
自訂面板元素
儘管 WPF 提供彈性版面配置控制項的陣列,但自訂的版面配置行為也可透過覆寫 ArrangeOverride 和 MeasureOverride (英文) 方法來達成。 藉由在這些覆寫方法內定義新的置放行為,即可達到自訂大小和位置的目的。
同樣地,您可以藉由覆寫其 ArrangeOverride (英文) 和 MeasureOverride (英文) 方法來定義以衍生類別 (例如 Canvas (部分機器翻譯) 或 Grid (部分機器翻譯)) 為基礎的自訂版面配置行為。
下列標記示範如何建立自訂 Panel (部分機器翻譯) 元素。 這個新的 Panel (部分機器翻譯) (已定義為 PlotPanel
) 支援透過使用硬式編碼的 x 和 y 座標來置放子元素。 在此範例中,Rectangle (部分機器翻譯) 元素 (未顯示) 置放於繪製點 50 (x) 和 50 (y) 上。
public:
ref class PlotPanel : Panel {
public:
PlotPanel () {};
protected:
// Override the default Measure method of Panel
virtual Size MeasureOverride(Size availableSize) override
{
Size^ panelDesiredSize = gcnew Size();
// In our example, we just have one child.
// Report that our panel requires just the size of its only child.
for each (UIElement^ child in InternalChildren)
{
child->Measure(availableSize);
panelDesiredSize = child->DesiredSize;
}
return *panelDesiredSize ;
}
protected:
virtual System::Windows::Size ArrangeOverride (Size finalSize) override
{
for each (UIElement^ child in InternalChildren)
{
double x = 50;
double y = 50;
child->Arrange(Rect(Point(x, y), child->DesiredSize));
}
return finalSize;
};
};
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
}
}
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 panelDesiredSize As Size = New Size()
' In our example, we just have one child.
' Report that our panel requires just the size of its only child.
For Each child As UIElement In InternalChildren
child.Measure(availableSize)
panelDesiredSize = child.DesiredSize
Next
Return panelDesiredSize
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 finalSize
End Function
End Class
若要檢視更複雜的自訂面板實作,請參閱建立自訂的內容換行面板範例 (英文)。
當地語系化/全球化支援
WPF 支援一些功能,能夠協助建立可當地語系化的 UI。
所有面板元素均原生支援 FlowDirection (部分機器翻譯) 屬性,使用此屬性可根據使用者的地區設定或語言設定,動態自動重排內容。 如需詳細資訊,請參閱FlowDirection。
SizeToContent (部分機器翻譯) 屬性提供一個機制,讓應用程式開發人員能夠預先考量當地語系化 UI 的需求。 使用此屬性的 WidthAndHeight (英文) 值,父 Window (部分機器翻譯) 一律會配合內容動態調整大小,而不會受到人為的高度或寬度限制約束。
DockPanel (部分機器翻譯)、Grid (部分機器翻譯) 和 StackPanel (部分機器翻譯) 全都是可當地語系化 UI 的絕佳選擇。 不過,Canvas (部分機器翻譯) 就不是理想的選項,因為其會以絕對方式置放內容,使得內容難以當地語系化。
如需建立具有可當地語系化使用者介面 (UI) 之 WPF 應用程式的其他資訊,請參閱使用自動版面配置概觀。