Przegląd Panele

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

Ten temat zawiera poniższe sekcje.

Klasa panelu

Panel jest klasą bazową dla wszystkich elementów, które zapewniają obsługę układu w programie Windows Presentation Foundation (WPF). Elementy pochodne Panel służą do umieszczania i rozmieszczania elementów w języku Extensible Application Markup Language (XAML) 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 przez zastąpienie ArrangeOverride metod i .MeasureOverride Aby uzyskać więcej informacji na temat niestandardowych zachowań układu, zobacz Niestandardowe elementy panelu.

Wspólne elementy członkowskie panelu

Wszystkie Panel elementy obsługują właściwości ustalania rozmiaru podstawowego i pozycjonowania zdefiniowane przez FrameworkElement, w tym Height, , Width, HorizontalAlignment, VerticalAlignmentMargini LayoutTransform. Aby uzyskać dodatkowe informacje na temat pozycjonowania właściwości zdefiniowanych przez FrameworkElementprogram , zobacz Wyrównanie, Marginesy i Wypełnienie — omówienie.

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 elementu panelu pochodnego za pomocą elementu Brush. Children reprezentuje podrzędną kolekcję elementów, z których Panel składa się element . InternalChildren reprezentuje zawartość kolekcji Children oraz te elementy członkowskie wygenerowane przez powiązanie danych. Oba elementy składają się z UIElementCollection elementów podrzędnych hostowanych w obiekcie nadrzędnym Panel.

Panel uwidacznia również dołączoną Panel.ZIndex właściwość, która może służyć do osiągnięcia kolejności warstwowej w pochodnym Panelobiekcie . Elementy członkowskie kolekcji panelu Children z wyższą Panel.ZIndex wartością pojawiają się 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 Definiuje również metodę OnRender , która może służyć do zastąpienia domyślnego zachowania prezentacji elementu Panel.

Dołączone właściwości

Pochodne elementy panelu umożliwiają szerokie wykorzystanie dołączonych 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, która jest faktycznie zdefiniowana 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 Omówienie właściwości dołączonych.

Elementy panelu pochodnego

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

Każdy element panelu hermetyzuje własną 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 ustawić elementy podrzędne według współrzędnych względem Canvas obszaru.
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 obiektu Grid można umieścić dokładnie przy użyciu Margin właściwości .
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 obiekcie 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ć" kolekcję elementów podrzędnych.
VirtualizingStackPanel Tak Rozmieszcza i wirtualizuje zawartość w jednym wierszu zorientowanym w poziomie lub w pionie.
WrapPanel Tak WrapPanel pozycje elementów podrzędnych w pozycji sekwencyjnej od lewej do prawej, powodując niezgodność zawartości do następnego wiersza na krawędzi pola zawierającego. Kolejność kolejności odbywa się sekwencyjnie od góry do dołu lub od prawej do lewej Orientation , w zależności od wartości właściwości.

Panele interfejsu użytkownika

Istnieje sześć klas paneli dostępnych w WPF, które są zoptymalizowane pod kątem obsługi scenariuszy interfejsu użytkownika: Canvas, , DockPanel, GridStackPanel, VirtualizingStackPanel, i WrapPanel. Te elementy panelu są łatwe w użyciu, uniwersalne i rozszerzalne na tyle dla większości aplikacji.

Każdy element pochodny Panel traktuje ograniczenia rozmiaru inaczej. Zrozumienie sposobu Panel obsługi ograniczeń w kierunku poziomym lub pionowym może sprawić, że układ będzie bardziej przewidywalny.

Nazwa panelu wymiar x Wymiar y
Canvas Ograniczone do zawartości Ograniczone do zawartości
DockPanel Ograniczone Ograniczone
StackPanel (Orientacja pionowa) Ograniczone Ograniczone do zawartości
StackPanel (Orientacja pozioma) Ograniczone do zawartości Ograniczone
Grid Ograniczone Ograniczone, z wyjątkiem przypadków Auto , gdy mają zastosowanie do wierszy i kolumn
WrapPanel Ograniczone do zawartości Ograniczone do zawartości

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

Kanwa

Element Canvas umożliwia pozycjonowanie zawartości zgodnie ze współrzędnymi bezwzględnymi x-iy . Elementy można narysować w unikatowej lokalizacji; lub, jeśli elementy zajmują te same współrzędne, kolejność ich wyświetlania w adiustacji określa kolejność, w jakiej elementy są rysowane.

Canvas zapewnia najbardziej elastyczną obsługę układu dowolnego Panelobiektu . Właściwości Height i Width służą do definiowania obszaru kanwy, a elementy wewnątrz są przypisywane współrzędnych bezwzględnych względem obszaru nadrzędnego Canvas. Cztery dołączone właściwości, Canvas.Left, Canvas.TopCanvas.Right i Canvas.Bottom, umożliwiają precyzyjną kontrolę nad umieszczaniem Canvasobiektów w obiekcie , dzięki czemu deweloper może umieścić i rozmieścić elementy dokładnie na ekranie.

ClipToBounds w kanwie

Canvas element podrzędny może być umieszczony w dowolnej pozycji na ekranie, nawet we współrzędnych, które znajdują się poza własnymi zdefiniowanymi elementami Height i Width. Ponadto Canvas nie ma to wpływu na wielkość swoich dzieci. W rezultacie element podrzędny może przerysować inne elementy poza prostokątem ograniczenia elementu nadrzędnego Canvas. Domyślnym zachowaniem elementu Canvas jest umożliwienie rysowania elementów podrzędnych poza granicami elementu nadrzędnego Canvas. Jeśli to zachowanie jest niepożądane, ClipToBounds właściwość można ustawić na truewartość . Canvas Powoduje to przycięcie do własnego rozmiaru. Canvas jest jedynym elementem układu, który umożliwia rysowania elementów podrzędnych poza jego granicami.

To zachowanie jest graficzne zilustrowane w przykładzie porównanie właściwości szerokości.

Definiowanie i używanie kanwy

Wystąpienie elementu Canvas można utworzyć po prostu przy użyciu języka XAML (Extensible Application Markup Language) lub kodu. W poniższym przykładzie pokazano, jak używać Canvas metody do bezwzględnego pozycjonowania zawartości. Ten kod tworzy trzy kwadraty o rozmiarze 100 pikseli. Pierwszy kwadrat jest czerwony, a jego lewa górna (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 ostatnio, wydaje się być na szczycie pozostałych dwóch kwadratów — czyli nakładające się części zakładają 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.

A typical Canvas Element.

DockPanel

Element DockPanel używa dołączonej właściwości jako ustawionej DockPanel.Dock w elementach zawartości podrzędnej, aby umieścić zawartość wzdłuż krawędzi kontenera. Gdy DockPanel.Dock jest ustawiona wartość Top lub Bottom, umieszcza elementy podrzędne powyżej lub poniżej siebie. Gdy DockPanel.Dock jest ustawiona wartość Left lub Right, umieszcza elementy podrzędne w lewo lub po prawej stronie siebie. Właściwość LastChildFill określa położenie końcowego elementu dodanego jako element podrzędny elementu DockPanel.

Możesz użyć DockPanel polecenia , aby ustawić grupę powiązanych kontrolek, takich jak zestaw przycisków. Alternatywnie możesz użyć go do utworzenia "posuniętych" interfejsu użytkownika, podobnie jak w programie Microsoft Outlook.

Ustalanie rozmiaru do zawartości

Jeśli jej Height właściwości i Width nie są określone, DockPanel rozmiary zawartości. Rozmiar może wzrosnąć lub zmniejszyć, aby uwzględnić rozmiar elementów podrzędnych. Jednak jeśli te właściwości są określone 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 LastChildFill właściwość na falsewartość .

Definiowanie i używanie elementu DockPanel

W poniższym przykładzie pokazano, jak partycjonować miejsce przy użyciu elementu DockPanel. Pięć Border elementów jest dodawanych jako elementy podrzędne elementu nadrzędnego DockPanel. Każda z nich używa innej właściwości pozycjonowania DockPanel elementu do partycjonowania miejsca. 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.

A typical DockPanel scenario.

Siatka

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

Czym różni się siatka od tabeli

Table i Grid udostępniają niektóre typowe funkcje, ale każdy z nich najlepiej nadaje się do różnych scenariuszy. Element jest Table przeznaczony do użytku w ramach zawartości przepływu (zobacz Omówienie dokumentu przepływu, aby uzyskać więcej informacji na temat zawartości przepływu). Siatki są najlepiej używane wewnątrz formularzy (w zasadzie w dowolnym miejscu poza zawartością przepływu). W programie FlowDocumentTable obsługiwane są zachowania zawartości przepływu, takie jak stronicowanie, ponowne przepływy kolumn i wybór zawartości, ale Grid nie. Z Grid drugiej strony najlepiej używać poza elementem z FlowDocument wielu powodów, w tym Grid dodawania elementów opartych na indeksie wierszy i kolumn, Table nie. Element Grid umożliwia warstwowanie zawartości podrzędnej, co pozwala na istnienie więcej niż jednego elementu w jednej komórce. Table Nie obsługuje warstw. Elementy podrzędne obiektu Grid mogą być absolutnie ustawione względem obszaru ich granic "komórki". Table nie obsługuje tej funkcji. Wreszcie, jest lżejsza Grid waga niż Table.

Zachowanie określania rozmiaru kolumn i wierszy

Kolumny i wiersze zdefiniowane w obiekcie Grid mogą korzystać z rozmiaru Star w celu proporcjonalnego rozłożenia pozostałego miejsca. Gdy Star jest zaznaczona jako wysokość lub szerokość wiersza lub kolumny, ta kolumna lub wiersz otrzymuje ważony odsetek pozostałych dostępnych miejsca. Jest to w przeciwieństwie do Autoelementu , który równomiernie rozproszy 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ę, aby proporcjonalnie rozłożyć przestrzeń z wartością HorizontalAlignmentStretch i VerticalAlignment można podzielić miejsce na partycje według procentu miejsca na ekranie. Grid jest jedynym panelem układu, który może w ten sposób dystrybuować miejsce.

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.

A typical Grid Element.

StackPanel

Element A StackPanel umożliwia "stos" 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 a DockPanel

Chociaż DockPanel może również "stos" elementów DockPanel podrzędnych i StackPanel nie generuje analogicznych wyników w niektórych scenariuszach użycia. Na przykład kolejność elementów podrzędnych może mieć wpływ na ich rozmiar w obiekcie DockPanel , ale nie w obiekcie StackPanel. Jest to spowodowane tym, że StackPanel miary w kierunku stosu w PositiveInfinityobiekcie , 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.

Screenshot: StackPanel vs. DockPanel screenshot

Definiowanie i używanie elementu StackPanel

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

A typical StackPanel element.

Virtualizingstackpanel

WPF udostępnia również odmianę StackPanel elementu, który automatycznie "wirtualizuje" powiązaną zawartość podrzędną danych. W tym kontekście słowo wirtualizowanie odwołuje się do techniki, za pomocą której podzbiór elementów jest generowany na podstawie większej liczby elementów danych na podstawie elementów widocznych 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 pośrednictwem funkcji udostępnianych przez VirtualizingPanelprogram ) oblicza widoczne elementy i współpracuje z elementem ItemContainerGenerator z ItemsControl elementu (na przykład 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, o ile zawartość znajduje się w granicach ScrollViewerobiektu . Znacznie poprawia to wydajność podczas hostowania wielu elementów podrzędnych.

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

<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 umieszczania elementów podrzędnych w pozycji sekwencyjnej od lewej do prawej, powodując niezgodność zawartości do następnego wiersza, gdy osiąga krawędź kontenera nadrzędnego. Zawartość może być zorientowana w poziomie lub w pionie. WrapPanel jest przydatna w przypadku prostych scenariuszy interfejsu użytkownika. Można go również użyć do zastosowania jednolitych rozmiarów do wszystkich elementów podrzędnych.

W poniższym przykładzie pokazano, jak utworzyć obiekt do WrapPanel wyświetlania Button kontrolek, 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.

A typical WrapPanel Element.

Zagnieżdżone elementy panelu

Panel elementy można zagnieżdżać w obrębie siebie, aby tworzyć złożone układy. Może to okazać się bardzo przydatne w sytuacjach, gdy 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 Grid element może być używany zamiast zagnieżdżonych paneli ze względu na jego elastyczność jako kontener układu. Może to zwiększyć wydajność aplikacji, zachowując niepotrzebne elementy z drzewa.

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

A UI that takes advantage of nested panels.

Niestandardowe elementy panelu

Chociaż WPF zapewnia tablicę elastycznych kontrolek układu, niestandardowe zachowania układu można również osiągnąć przez zastąpienie ArrangeOverride metod 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) można zdefiniować przez zastąpienie ich ArrangeOverride metod i MeasureOverride .

Poniższy znacznik pokazuje, jak utworzyć element niestandardowy Panel . Ten nowy Panelelement , zdefiniowany jako PlotPanel, obsługuje pozycjonowanie elementów podrzędnych za pomocą ustalonych współrzędnych x-iy. W tym przykładzie Rectangle element (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 Tworzenie niestandardowego panelu opakowującego zawartość Przykład.

Obsługa lokalizacji/globalizacji

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

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

Właściwość SizeToContent udostępnia mechanizm, który umożliwia deweloperom aplikacji przewidywanie potrzeb zlokalizowanego interfejsu użytkownika. WidthAndHeight Korzystając z wartości tej właściwości, element nadrzędny Window zawsze rozmiaruje dynamicznie, aby dopasować zawartość i nie jest ograniczany przez ograniczenia sztucznej 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 przy użyciu interfejsów użytkownika lokalizowalnych, zobacz Omówienie automatycznego układu.

Zobacz też