Udostępnij za pośrednictwem


Przegląd paneli

Panel elementy to komponenty, które kontrolują renderowanie elementów — ich rozmiar i wymiary, położenie oraz rozmieszczenie treści podrzędnych. Program Windows Presentation Foundation (WPF) udostępnia szereg wstępnie zdefiniowanych elementów Panel, a także możliwość konstruowania niestandardowych elementów Panel.

Ten temat zawiera następujące sekcje.

Klasa Panelowa

Panel jest klasą bazową dla wszystkich elementów, które zapewniają obsługę układu w programie Windows Presentation Foundation (WPF). Pochodne elementy Panel służą do umieszczania i rozmieszczania elementów w języku XAML (Extensible Application Markup Language) i kodzie.

WPF zawiera kompleksowy zestaw implementacji paneli pochodnych, które umożliwiają wiele złożonych układów. Te klasy pochodne uwidaczniają właściwości i metody, które umożliwiają korzystanie z większości standardowych scenariuszy interfejsu użytkownika. Deweloperzy, którzy nie mogą znaleźć zachowania układu podrzędnego spełniającego ich potrzeby, mogą tworzyć nowe układy, przesłaniając metody ArrangeOverride i MeasureOverride. Aby uzyskać więcej informacji na temat niestandardowych zachowań układu, zobacz niestandardowe elementy panelu.

Wspólni członkowie panelu

Wszystkie elementy Panel obsługują właściwości określania rozmiaru podstawowego i pozycjonowania zdefiniowane przez FrameworkElement, w tym Height, Width, HorizontalAlignment, VerticalAlignment, Margini LayoutTransform. Aby uzyskać dodatkowe informacje na temat właściwości pozycjonowania zdefiniowanych przez FrameworkElement, zapoznaj się z omówieniem wyrównania, marginesów i odstępów.

Panel uwidacznia dodatkowe właściwości, które mają krytyczne znaczenie w zrozumieniu i używaniu układu. Właściwość Background służy do wypełniania obszaru między granicami pochodnego elementu panelu za pomocą Brush. Children reprezentuje podrzędną kolekcję elementów, z których składa się Panel. InternalChildren reprezentuje zawartość kolekcji Children oraz elementy wygenerowane przez powiązanie danych. Oba składają się z UIElementCollection elementów podrzędnych umieszczonych w nadrzędnym Panel.

Panel także udostępnia właściwość dołączoną Panel.ZIndex, która służy do osiągnięcia porządku warstwowego w ramach pochodnej Panel. Członkowie kolekcji Children panelu z wyższą wartością Panel.ZIndex są wyświetlane przed elementami o niższej Panel.ZIndex wartości. Jest to szczególnie przydatne w przypadku paneli, takich jak Canvas i Grid, które umożliwiają dzieciom współdzielenie tej samej przestrzeni współrzędnych.

Panel również definiuje metodę OnRender, która może służyć do zastąpienia domyślnego zachowania prezentacji Panel.

Dołączone właściwości

Elementy pochodne panelu szeroko wykorzystują przypisane właściwości. Dołączona właściwość jest wyspecjalizowaną formą właściwości zależności, która nie ma konwencjonalnej właściwości środowiska uruchomieniowego języka wspólnego (CLR) "otoka". Dołączone właściwości mają wyspecjalizowaną składnię w języku Extensible Application Markup Language (XAML), które można zobaczyć w kilku poniższych przykładach.

Jednym z celów dołączonej właściwości jest umożliwienie elementom podrzędnym przechowywania unikatowych wartości właściwości faktycznie zdefiniowanej przez element nadrzędny. Zastosowanie tej funkcji polega na tym, że elementy podrzędne informują rodzica o tym, jak mają być prezentowane w interfejsie użytkownika, co jest niezwykle przydatne w przypadku układu aplikacji. Aby uzyskać więcej informacji, zobacz Przegląd dołączonych właściwości.

Elementy panelu pochodnego

Wiele obiektów pochodzi z Panel, ale nie wszystkie z nich są przeznaczone do użycia jako dostawcy układu głównego. Istnieją sześć zdefiniowanych klas paneli (Canvas, DockPanel, Grid, StackPanel, VirtualizingStackPaneli WrapPanel) przeznaczonych specjalnie do tworzenia interfejsu użytkownika aplikacji.

Każdy element panelu zawiera swoją specjalną funkcjonalność, jak pokazano w poniższej tabeli.

Nazwa elementu Panel interfejsu użytkownika? Opis
Canvas Tak Definiuje obszar, w którym można jawnie umieścić elementy podrzędne na podstawie współrzędnych w odniesieniu do obszaru Canvas.
DockPanel Tak Definiuje obszar, w którym można rozmieścić elementy podrzędne w poziomie lub w pionie względem siebie.
Grid Tak Definiuje elastyczny obszar siatki składający się z kolumn i wierszy. Elementy podrzędne Grid można precyzyjnie ustawić przy użyciu właściwości Margin.
StackPanel Tak Rozmieszcza elementy podrzędne w jedną linię, która może być zorientowana w poziomie lub w pionie.
TabPanel Nie Obsługuje układ przycisków tabulacji w TabControl.
ToolBarOverflowPanel Nie Rozmieszcza zawartość w kontrolce ToolBar.
UniformGrid Nie UniformGrid służy do rozmieszczania elementów podrzędnych w siatce ze wszystkimi równymi rozmiarami komórek.
VirtualizingPanel Nie Udostępnia klasę bazową dla paneli, które mogą "wirtualizować" swoją kolekcję dzieci.
VirtualizingStackPanel Tak Rozmieszcza i wirtualizuje zawartość w jednym wierszu zorientowanym w poziomie lub w pionie.
WrapPanel Tak WrapPanel umieszcza elementy podrzędne w pozycji sekwencyjnej od lewej do prawej, przenosząc zawartość do następnej linii na krawędzi pola zawierającego. Kolejność kolejności odbywa się sekwencyjnie od góry do dołu lub od prawej do lewej, w zależności od wartości właściwości Orientation.

Panele interfejsu użytkownika

W WPF dostępnych jest sześć klas paneli zoptymalizowanych pod kątem obsługi scenariuszy interfejsu użytkownika: Canvas, DockPanel, Grid, StackPanel, VirtualizingStackPaneli WrapPanel. Te elementy panelu są łatwe w użyciu, uniwersalne i rozszerzalne na tyle dla większości aplikacji.

Każdy pochodny element Panel traktuje ograniczenia rozmiaru inaczej. Zrozumienie, w jaki sposób Panel obsługuje ograniczenia w kierunku poziomym lub pionowym, może sprawić, że układ będzie bardziej przewidywalny.

nazwa panelu x-dimension wymiar y
Canvas Ograniczone w zakresie zawartości Ograniczone przez zawartość
DockPanel Ograniczone Ograniczone
StackPanel (orientacja pionowa) Ograniczone Ograniczone do treści
StackPanel (orientacja pozioma) Ograniczone do treści Ograniczone
Grid Ograniczone Ograniczone, z wyjątkiem przypadków, w których Auto mają zastosowanie do wierszy i kolumn
WrapPanel Ograniczone do treści Ograniczone do treści

Bardziej szczegółowe opisy i przykłady użycia każdego z tych elementów można znaleźć poniżej.

Płótno

Element Canvas umożliwia pozycjonowanie zawartości zgodnie z bezwzględnymi x- i współrzędnymi y-. Elementy można narysować w niepowtarzalnej lokalizacji; lub, jeśli elementy zajmują te same współrzędne, kolejność ich wyświetlania w znacznikach określa kolejność rysowania elementów.

Canvas zapewnia najbardziej elastyczne wsparcie układu ze wszystkich Panel. Właściwości Height i Width służą do definiowania obszaru kanwy, a elementom wewnątrz przypisywane są współrzędne bezwzględne w odniesieniu do obszaru nadrzędnego Canvas. Cztery dołączone właściwości, Canvas.Left, Canvas.Top, Canvas.Right i Canvas.Bottom, umożliwiają precyzyjną kontrolę nad umieszczaniem obiektów w Canvas, umożliwiając deweloperowi położenie i rozmieszczanie elementów dokładnie na ekranie.

ClipToBounds w kanwie

Canvas może umieszczać elementy podrzędne w dowolnym miejscu na ekranie, nawet na współrzędnych znajdujących się poza jego własnymi zdefiniowanymi granicami Height i Width. Ponadto Canvas nie ma wpływu na wielkość swoich dzieci. W rezultacie element podrzędny może przerysować inne elementy poza obszarem ograniczonym prostokątem elementu nadrzędnego Canvas. Domyślne zachowanie Canvas polega na umożliwieniu rysowania dzieci poza granicami elementu nadrzędnego Canvas. Jeśli to zachowanie jest niepożądane, właściwość ClipToBounds można ustawić na true. Powoduje to, że Canvas jest przycinane do własnego rozmiaru. Canvas jest jedynym elementem układu, który umożliwia rysowanie elementów podrzędnych poza jego granicami.

To zachowanie jest graficznie zilustrowane w przykładzie Width Properties Comparison Sample.

Definiowanie i używanie kanwy

Canvas można utworzyć po prostu przy użyciu rozszerzalnego języka znaczników aplikacji (XAML) lub kodu. W poniższym przykładzie pokazano, jak używać Canvas do bezwzględnego pozycjonowania zawartości. Ten kod tworzy trzy kwadraty o rozmiarze 100 pikseli. Pierwszy kwadrat jest czerwony, a jego lewy górny (x, y) pozycja jest określona jako (0, 0). Drugi kwadrat jest zielony, a lewa górna pozycja to (100, 100), tuż poniżej i z prawej strony pierwszego kwadratu. Trzeci kwadrat jest niebieski, a lewa górna pozycja to (50, 50), w związku z czym obejmuje prawą dolną ćwiartkę pierwszego kwadratu i lewą górną ćwiartkę drugiego. Ponieważ trzeci kwadrat jest układany ostatni, wydaje się być na wierzchu pozostałych dwóch pól — czyli nakładające się części przyjmują kolor trzeciego pola.


// 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>

Skompilowana aplikacja daje nowy interfejs użytkownika, który wygląda następująco.

Typowy element Kanwy.

DockPanel

Element DockPanel używa dołączonej właściwości DockPanel.Dock, która jest ustawiona w podrzędnych elementach zawartości, do pozycjonowania zawartości wzdłuż krawędzi kontenera. Gdy DockPanel.Dock jest ustawiony na wartość Top lub Bottom, umieszcza elementy podrzędne jeden nad drugim lub jeden pod drugim. Gdy DockPanel.Dock jest ustawione na Left lub Right, elementy podrzędne są ustawiane obok siebie po lewej lub prawej stronie. Właściwość LastChildFill określa położenie ostatniego elementu dodanego jako element podrzędny DockPanel.

Za pomocą DockPanel można ustawić grupę powiązanych kontrolek, takich jak zestaw przycisków. Alternatywnie, możesz użyć go do utworzenia panelowego interfejsu użytkownika, podobnego do tego odnalezionego w programie Microsoft Outlook.

Dopasowanie rozmiaru do zawartości

Jeśli nie określono właściwości Height i Width, DockPanel dopasowuje się do swojej zawartości. Rozmiar może się zwiększać lub zmniejszać, aby uwzględnić rozmiar elementów podrzędnych. Jednak po określeniu tych właściwości i nie ma już miejsca dla następnego określonego elementu podrzędnego, DockPanel nie wyświetla tego elementu podrzędnego ani kolejnych elementów podrzędnych i nie mierzy kolejnych elementów podrzędnych.

LastChildFill

Domyślnie ostatnie podrzędne elementu DockPanel będzie wypełniać pozostałe, nieprzydzielone miejsce. Jeśli to zachowanie nie jest pożądane, ustaw właściwość LastChildFill na wartość false.

Definiowanie i używanie elementu DockPanel

W poniższym przykładzie pokazano, jak partycjonować miejsce przy użyciu DockPanel. Dodawane jest pięć elementów Border jako dzieci elementu nadrzędnego DockPanel. Każda używa innej właściwości pozycjonowania DockPanel do partycjonowania przestrzeni. Ostatni element "wypełnia" pozostałe, nieprzydzielone miejsce.


// 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>

Skompilowana aplikacja daje nowy interfejs użytkownika, który wygląda następująco.

Typowy scenariusz DockPanel.

Siatka

Element Grid scala funkcje bezwzględnego pozycjonowania i kontrolki danych tabelarycznych. Grid umożliwia łatwe pozycjonowanie i stylizowanie elementów. Grid umożliwia definiowanie elastycznych grup wierszy i kolumn, a nawet udostępnia mechanizm udostępniania informacji o rozmiarze między wieloma elementami Grid.

Czym różni się siatka od tabeli

Table i Grid mają kilka typowych funkcji, ale każdy z nich najlepiej nadaje się do różnych scenariuszy. Table jest zaprojektowany do użycia w treści przepływu (zobacz Omówienie dokumentu przepływu, aby uzyskać więcej informacji na temat treści przepływu). Siatki są najlepiej używane wewnątrz formularzy (w zasadzie w dowolnym miejscu poza zawartością przepływu). W FlowDocument, Table obsługuje zachowania zawartości przepływu, takie jak stronicowanie, przepływ kolumn i wybór zawartości, podczas gdy Grid nie. Z drugiej strony Grid najlepiej używać poza FlowDocument z wielu powodów, w tym Grid dodaje elementy na podstawie indeksu wierszy i kolumn, Table nie. Element Grid umożliwia warstwowanie zawartości podrzędnej, umożliwiając istnienie więcej niż jednego elementu w ramach jednej "komórki". Table nie obsługuje warstwowania. Elementy podrzędne Grid mogą być absolutnie pozycjonowane względem obszaru granic ich "komórki". Table nie obsługuje tej funkcji. Na koniec Grid jest lżejsza niż Table.

Zachowanie dotyczące rozmiaru kolumn i wierszy

Kolumny i wiersze zdefiniowane w Grid mogą korzystać z określania rozmiaru przez Star, aby proporcjonalnie rozłożyć pozostałe miejsce. Gdy Star jest zaznaczona jako wysokość lub szerokość wiersza lub kolumny, ta kolumna lub wiersz otrzymuje ważoną część pozostałego dostępnego miejsca. Jest to w przeciwieństwie do Auto, która równomiernie dystrybuuje przestrzeń na podstawie rozmiaru zawartości w kolumnie lub wierszu. Ta wartość jest wyrażona jako * lub 2* w przypadku używania języka XAML (Extensible Application Markup Language). W pierwszym przypadku wiersz lub kolumna będzie otrzymywać jeden raz dostępne miejsce, w drugim przypadku dwa razy itd. Łącząc tę technikę proporcjonalnego rozdzielania przestrzeni z wartościami HorizontalAlignment i VerticalAlignment dla Stretch, można podzielić przestrzeń według procentu zajmowanego ekranu. Grid jest jedynym panelem kompozycji, który może w ten sposób rozmieszczać przestrzeń.

Definiowanie i używanie siatki

W poniższym przykładzie pokazano, jak utworzyć interfejs użytkownika podobny do tego, który można znaleźć w oknie dialogowym Uruchamianie dostępnym w menu Start systemu Windows.


// 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

Skompilowana aplikacja daje nowy interfejs użytkownika, który wygląda następująco.

Typowy element siatki.

StackPanel

StackPanel umożliwia układanie elementów w przypisanym kierunku. Domyślny kierunek stosu to pionowy. Właściwość Orientation może służyć do sterowania przepływem zawartości.

StackPanel kontra DockPanel

Chociaż DockPanel może również układać elementy podrzędne w stos, DockPanel i StackPanel nie dają podobnych wyników w niektórych scenariuszach użycia. Na przykład kolejność elementów podrzędnych może wpływać na ich rozmiar w DockPanel, ale nie w StackPanel. Dzieje się tak, ponieważ StackPanel mierzy kierunek stosu w PositiveInfinity, natomiast DockPanel mierzy tylko dostępny rozmiar.

W poniższym przykładzie pokazano tę kluczową różnicę.


// 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>

Różnica w zachowaniu renderowania jest widoczna na tej ilustracji.

Zrzut ekranu: StackPanel a DockPanel zrzut ekranu

Definiowanie i używanie elementu StackPanel

W poniższym przykładzie pokazano, jak za pomocą StackPanel utworzyć zestaw przycisków umieszczonych w pionie. W przypadku pozycjonowania w poziomie ustaw właściwość Orientation na wartość 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

Skompilowana aplikacja daje nowy interfejs użytkownika, który wygląda następująco.

typowy element StackPanel.

WirtualizacjaStackPanel

WPF udostępnia również odmianę elementu StackPanel, który automatycznie "wirtualizuje" zawartość podrzędnie związaną z danymi. W tym kontekście słowo 'wirtualizować' odnosi się do techniki, dzięki której podzbiór elementów jest generowany z większej liczby elementów danych, w oparciu o te, które są widoczne na ekranie. Jest to intensywne, zarówno pod względem pamięci, jak i procesora, generowanie dużej liczby elementów interfejsu użytkownika, gdy tylko kilka może znajdować się na ekranie w danym momencie. VirtualizingStackPanel (za pomocą funkcji udostępnianych przez VirtualizingPanel) oblicza widoczne elementy i współpracuje z ItemContainerGenerator z ItemsControl (np. ListBox lub ListView), aby tworzyć tylko elementy dla widocznych elementów.

Element VirtualizingStackPanel jest automatycznie ustawiany jako host elementów dla kontrolek, takich jak ListBox. Podczas hostowania kolekcji powiązanej z danymi, zawartość jest automatycznie zwirtualizowana, pod warunkiem, że mieści się w granicach ScrollViewer. Znacznie poprawia to wydajność podczas hostowania wielu elementów podrzędnych.

Poniższy fragment kodu pokazuje, jak używać VirtualizingStackPanel jako hosta elementów. Aby można było przeprowadzić wirtualizację, właściwość VirtualizingStackPanel.IsVirtualizingProperty musi być ustawiona na true (wartość domyślna).

<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 służy do rozmieszczania elementów podrzędnych w kolejności od lewej do prawej, przenosząc zawartość do następnego wiersza, gdy osiągnie krawędź kontenera nadrzędnego. Zawartość może być zorientowana w poziomie lub w pionie. WrapPanel jest przydatna w przypadku prostych, płynnych scenariuszy interfejsu użytkownika. Można go także użyć do jednolitego dostosowania rozmiarów wszystkich elementów podrzędnych.

W poniższym przykładzie pokazano, jak utworzyć WrapPanel, aby wyświetlić Button kontrolki, które są zawijane po dotarciu do krawędzi kontenera.


// 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>

Skompilowana aplikacja daje nowy interfejs użytkownika, który wygląda następująco.

Typowy element WrapPanel.

Zagnieżdżone elementy panelu

Panel element można zagnieżdżać wewnątrz siebie, aby tworzyć złożone układy. Może to okazać się bardzo przydatne w sytuacjach, w których jeden Panel jest idealny dla części interfejsu użytkownika, ale może nie spełniać potrzeb innej części interfejsu użytkownika.

Nie ma praktycznego ograniczenia ilości zagnieżdżania, które aplikacja może obsługiwać, jednak zazwyczaj najlepiej ograniczyć aplikację do używania tylko tych paneli, które są rzeczywiście niezbędne dla żądanego układu. W wielu przypadkach można użyć elementu Grid zamiast zagnieżdżonych paneli ze względu na jego elastyczność jako pojemnika układu. Może to zwiększyć wydajność aplikacji poprzez usunięcie niepotrzebnych elementów z drzewa.

W poniższym przykładzie pokazano, jak utworzyć interfejs użytkownika, który wykorzystuje zagnieżdżone elementy Panel w celu osiągnięcia określonego układu. W tym konkretnym przypadku element DockPanel służy do zapewnienia struktury dla interfejsu użytkownika, a zagnieżdżone elementy StackPanel, Gridi Canvas są używane do precyzyjnego ustawiania elementów podrzędnych w obrębie nadrzędnym 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)

Skompilowana aplikacja daje nowy interfejs użytkownika, który wygląda następująco.

interfejs użytkownika korzystający z zagnieżdżonych paneli.

Niestandardowe elementy panelu

Chociaż platforma WPF udostępnia tablicę elastycznych kontrolek układu, niestandardowe zachowania układu można również osiągnąć, przesłaniając metody ArrangeOverride i MeasureOverride. Niestandardowe ustalanie rozmiaru i pozycjonowanie można osiągnąć przez zdefiniowanie nowych zachowań pozycjonowania w ramach tych metod zastępowania.

Podobnie niestandardowe zachowania układu oparte na klasach pochodnych (takich jak Canvas lub Grid) mogą być definiowane przez zastąpienie ich metod ArrangeOverride i MeasureOverride.

Poniższy znacznik pokazuje, jak utworzyć niestandardowy element Panel. Ta nowa Panel, zdefiniowana jako PlotPanel, obsługuje pozycjonowanie elementów podrzędnych przy użyciu zakodowanych trwale x- i współrzędnych y-. W tym przykładzie element Rectangle (nie pokazany) jest umieszczony w punkcie wykresu 50 (x) i 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

Aby wyświetlić bardziej złożoną niestandardową implementację panelu, zobacz Przykład niestandardowego panelu obejmującego zawartość.

Obsługa lokalizacji/globalizacji

WPF obsługuje wiele funkcji, które pomagają w tworzeniu lokalizowalnego interfejsu użytkownika.

Wszystkie elementy panelu natywnie obsługują właściwość FlowDirection, która może służyć do dynamicznego ponownego przepływu zawartości na podstawie ustawień regionalnych lub ustawień językowych użytkownika. Aby uzyskać więcej informacji, zobacz FlowDirection.

Właściwość SizeToContent udostępnia mechanizm, który umożliwia deweloperom aplikacji przewidywanie potrzeb zlokalizowanego interfejsu użytkownika. Używając wartości WidthAndHeight tej właściwości, nadrzędne Window zawsze dynamicznie zmienia rozmiar, aby dopasować się do zawartości i nie jest ograniczane przez sztuczne ograniczenia wysokości lub szerokości.

DockPanel, Gridi StackPanel są dobrymi wyborami dla lokalizowalnego interfejsu użytkownika. Canvas nie jest to jednak dobry wybór, ponieważ umieszcza zawartość absolutnie, co utrudnia lokalizowanie.

Aby uzyskać dodatkowe informacje na temat tworzenia aplikacji WPF z interfejsami użytkownika lokalizowalnymi (UI), zobacz Use Automatic Layout Overview (Omówienie automatycznego układu).

Zobacz też