Partager via


Vue d'ensemble de Panel

Mise à jour : novembre 2007

Les éléments Panel sont des composants qui contrôlent le rendu des éléments : leurs taille et dimensions, leur position et la disposition de leur contenu enfant. Windows Presentation Foundation (WPF) fournit un nombre d'éléments Panel prédéfinis ainsi que la possibilité de construire des éléments Panel personnalisés.

Cette rubrique contient les sections suivantes.

  • La classe Panel

  • Membres communs aux éléments Panel

  • Éléments Panel dérivés

  • Panneaux d'interface utilisateur

  • Éléments Panel imbriqués

  • Éléments Panel personnalisés

  • Prise en charge de la localisation/globalisation

  • Rubriques connexes

La classe Panel

Panel est la classe de base pour tous les éléments qui offrent une prise en charge de la disposition dans Windows Presentation Foundation (WPF). Les éléments Panel dérivés sont utilisés pour positionner et organiser les UIElements en XAML (Extensible Application Markup Language) et dans le code.

WPF comprend une suite complète d'implémentations de panneaux dérivés permettant de nombreuses dispositions complexes. Ces classes dérivées exposent des propriétés et des méthodes qui permettent d'implémenter la plupart des scénarios d'interface utilisateur (UI). Les développeurs qui ne parviennent pas à trouver le comportement de disposition d'enfants qui répond à leur besoin peuvent créer de nouvelles dispositions en remplaçant les méthodes ArrangeOverride et MeasureOverride. Pour plus d'informations sur les comportements de dispositions personnalisés, consultez Éléments Panel personnalisés.

XAMLPad

XAMLPad est un outil qui facilite le développement d'interfaces utilisateur basées sur XAML (Extensible Application Markup Language) en analysant le balisage en temps réel et en affichant les résultats dans une fenêtre. Cet outil est très utile pour manipuler les dispositions. Vous souhaiterez peut-être que l'application soit ouverte afin de visualiser les résultats des différents exemples XAML (Extensible Application Markup Language) contenus dans cette rubrique. Pour plus d'informations, consultez XAMLPad.

Membres communs aux éléments Panel

Tous les éléments Panel prennent en charge les propriétés de dimensionnement et de positionnement de base définies par FrameworkElement, telles que Height, Width, HorizontalAlignment, VerticalAlignment, Margin et LayoutTransform. Pour plus d'informations sur les propriétés de positionnement définies par FrameworkElement, consultez Vue d'ensemble de l'alignement, des marges et du remplissage.

Panel expose des propriétés supplémentaires qui sont d'une importance primordiale pour comprendre et utiliser la disposition. La propriété Background est utilisée pour remplir la zone située entre les bords d'un élément Panel dérivé à l'aide d'un Brush. Children représente la collection d'enfants de UIElements dont Panel est composé. InternalChildren représente le contenu de la collection Children, plus les membres générés par liaison de données. Tous deux consistent en une UIElementCollection d'éléments enfants hébergés dans le Panel parent.

Panel expose également une propriété ZIndex qui peut être utilisée pour effectuer un ordre superposé dans un Panel dérivé. Les membres d'une collection de Children d'un panneau dont la valeur ZIndex est supérieure apparaissent en face de ceux dont la valeur ZIndex est inférieure. Ceci est particulièrement utile pour les panneaux tels que Canvas et Grid qui permettent à des enfants de partager le même espace de coordonnées.

Panel définit également la méthode OnRender, qui peut être utilisée pour remplacer le comportement de présentation par défaut de Panel.

Propriétés attachées

Les éléments Panel dérivés utilisent très souvent des propriétés attachées. Une propriété attachée est une forme spécialisée de propriété de dépendance qui ne possède pas le « wrapper » de propriété classique du Common Language Runtime (CLR). Les propriétés attachées ont une syntaxe spécialisée en XAML (Extensible Application Markup Language), ce qui est montré dans plusieurs des exemples suivants.

L'un des objectifs d'une propriété attachée est de permettre à des éléments enfants de stocker des valeurs uniques d'une propriété qui est réellement définie par un élément parent. Une application de cette fonctionnalité est que les éléments enfants informent le parent sur la manière dont ils souhaitent être présentés dans l'interface utilisateur (UI), ce qui est extrêmement utile pour la disposition d'application. Pour plus d'informations, consultez Vue d'ensemble des propriétés attachées.

Éléments Panel dérivés

De nombreux objets dérivent de Panel, mais ils ne sont pas tous destinés à être utilisés comme des fournisseurs de disposition racine. Il existe six classes Panel définies (Canvas, DockPanel, Grid, StackPanel, VirtualizingStackPanel et WrapPanel) qui sont conçues spécifiquement pour créer une interface utilisateur d'application.

Chaque élément Panel encapsule sa propre fonctionnalité particulière, comme le montre le tableau suivant.

Nom de l'élément

Panneau UI ?

Description

Canvas

Oui

Définit une zone dans laquelle vous pouvez positionner explicitement des éléments enfants par leurs coordonnées relatives à la zone du Canvas.

DockPanel

Oui

Définit une zone dans laquelle vous pouvez réorganiser des éléments enfants soit horizontalement soit verticalement, les uns par rapport aux autres.

Grid

Oui

Définit une grille flexible qui se compose de colonnes et de lignes. Les éléments enfants de Grid peuvent être positionnés avec précision à l'aide de la propriété Margin.

StackPanel

Oui

Réorganise des éléments enfants sur une seule ligne pouvant être orientée horizontalement ou verticalement.

TabPanel

Non

Gère la disposition de boutons d'onglet dans un TabControl.

ToolBarOverflowPanel

Non

Réorganise le contenu dans un contrôle ToolBar.

UniformGrid

Non

UniformGrid est utilisé pour réorganiser des enfants dans une grille dont les cellules sont toutes de même taille.

VirtualizingPanel

Non

Fournit une classe de base pour des panneaux qui peuvent « virtualiser » leur collection d'enfants.

VirtualizingStackPanel

Oui

Réorganise et virtualise le contenu sur une seule ligne orientée horizontalement ou verticalement.

WrapPanel

Oui

WrapPanel positionne les éléments enfants selon un ordre séquentiel de gauche à droite, en envoyant le contenu à la ligne suivante, à l'extrémité de la zone conteneur. L'ordre séquentiel ultérieur est établi de haut en bas ou de droite à gauche, en fonction de la valeur de la propriété Orientation.

Panneaux d'interface utilisateur

Il existe six classes Panel disponibles dans WPF qui sont optimisées pour prendre en charge des scénarios d'interface utilisateur : Canvas, DockPanel, Grid, StackPanel, VirtualizingStackPanel et WrapPanel. Ces éléments Panel sont faciles à utiliser, polyvalents et suffisamment extensibles pour la plupart des applications.

Chaque élément Panel dérivé traite différemment les contraintes liées au dimensionnement. En comprenant comment Panel gère les contraintes, soit dans le sens horizontal soit dans le sens vertical, il est plus facile de prévoir la disposition.

Nom du panneau

Dimension x

Dimension y

Canvas

Limité au contenu

Limité au contenu

DockPanel

Limité

Limité

StackPanel (orientation verticale)

Limité

Limité au contenu

StackPanel (orientation horizontale)

Limité au contenu

Limité

Grid

Limité

Limité, sauf dans les cas où Auto s'applique aux lignes et aux colonnes

WrapPanel

Limité au contenu

Limité au contenu

Des descriptions plus détaillées ainsi que des exemples d'utilisation de chacun de ces éléments sont fournis ci-dessous.

Canvas

L'élément Canvas permet de positionner du contenu en fonction des coordonnées absolues x et y. Les éléments peuvent être dessinés dans un emplacement unique, ou, si des éléments occupent les mêmes coordonnées, l'ordre dans lequel ces éléments sont dessinés est déterminé par l'ordre dans lequel ils apparaissent dans le balisage.

Canvas est le Panel qui fournit la prise en charge de la disposition la plus souple. Les propriétés Height et Width sont utilisées pour définir la zone de dessin, et des coordonnées absolues par rapport à la zone du Canvas parent sont assignées aux éléments qui sont à l'intérieur de cette zone. Quatre propriétés attachées, Left, Top, Right et Bottom, permettent de bien contrôler le placement des objets à l'intérieur d'un Canvas, donnant ainsi la possibilité au développeur de positionner et de réorganiser les éléments avec précision sur l'écran.

ClipToBound dans une zone de dessin

Canvas peut positionner des éléments enfants à n'importe quelle position sur l'écran, même à des coordonnées qui sont en dehors de ses propres Height et Width définies. De plus, Canvas n'est pas affecté par la taille de ses enfants. Il en résulte qu'un élément enfant a la possibilité de recouvrir d'autres éléments situés en dehors du rectangle englobant du Canvas parent. Le comportement par défaut de Canvas est de permettre à des enfants d'être dessinés en dehors des limites du Canvas parent. Si ce comportement n'est pas souhaité; il est possible d'affecter true à la propriété ClipToBounds. Cela entraîne le découpage du Canvas à sa propre taille. Canvas est le seul élément de disposition qui permet à des enfants d'être dessinés en dehors de ses limites.

Ce comportement est illustré graphiquement dans Comparaison des propriétés Width, exemple.

Définition et utilisation de Canvas

Canvas peut être instancié en utilisant simplement XAML (Extensible Application Markup Language) ou du code. L'exemple suivant montre comment utiliser Canvas pour positionner du contenu de façon absolue. Ce code génère trois carrés de 100 pixels de côté. Le premier carré est rouge, et la position (x, y) de son angle supérieur gauche est spécifiée à (0, 0). Le deuxième carré est vert, et la position de son angle supérieur gauche est (100, 100), juste en dessous et à droite du premier carré. Le troisième carré est bleu, et la position de son angle supérieur gauche est (50, 50), il recouvre ainsi le quadrant inférieur droit du premier carré et le quadrant supérieur gauche du deuxième. Le troisième carré étant placé en dernier, il semble se trouver au-dessus des deux autres, c'est-à-dire que les parties qui se chevauchent prennent la couleur du troisième carré.

WindowTitle = "Canvas Sample"
'Create a Canvas as the root Panel
Dim myParentCanvas As New Canvas()
myParentCanvas.Width = 400
myParentCanvas.Height = 400

' Define child Canvas elements
Dim myCanvas1 As New Canvas()
myCanvas1.Background = Brushes.Red
myCanvas1.Height = 100
myCanvas1.Width = 100
Canvas.SetTop(myCanvas1, 0)
Canvas.SetLeft(myCanvas1, 0)

Dim myCanvas2 As New Canvas()
myCanvas2.Background = Brushes.Green
myCanvas2.Height = 100
myCanvas2.Width = 100
Canvas.SetTop(myCanvas2, 100)
Canvas.SetLeft(myCanvas2, 100)

Dim myCanvas3 As New Canvas()
myCanvas3.Background = Brushes.Blue
myCanvas3.Height = 100
myCanvas3.Width = 100
Canvas.SetTop(myCanvas3, 50)
Canvas.SetLeft(myCanvas3, 50)

' Add child elements to the Canvas' Children collection
myParentCanvas.Children.Add(myCanvas1)
myParentCanvas.Children.Add(myCanvas2)
myParentCanvas.Children.Add(myCanvas3)

' Add the parent Canvas as the Content of the Window Object
Me.Content = myParentCanvas
// Create the application's main window
mainWindow = new Window ();
mainWindow.Title = "Canvas Sample";

// Create the Canvas
myParentCanvas = new Canvas();
myParentCanvas.Width = 400;
myParentCanvas.Height = 400;

// Define child Canvas elements
myCanvas1 = new Canvas();
myCanvas1.Background = Brushes.Red;
myCanvas1.Height = 100;
myCanvas1.Width = 100;
Canvas.SetTop(myCanvas1, 0);
Canvas.SetLeft(myCanvas1, 0);

myCanvas2 = new Canvas();
myCanvas2.Background = Brushes.Green;
myCanvas2.Height = 100;
myCanvas2.Width = 100;
Canvas.SetTop(myCanvas2, 100);
Canvas.SetLeft(myCanvas2, 100);

myCanvas3 = new Canvas();
myCanvas3.Background = Brushes.Blue;
myCanvas3.Height = 100;
myCanvas3.Width = 100;
Canvas.SetTop(myCanvas3, 50);
Canvas.SetLeft(myCanvas3, 50);

// Add child elements to the Canvas' Children collection
myParentCanvas.Children.Add(myCanvas1);
myParentCanvas.Children.Add(myCanvas2);
myParentCanvas.Children.Add(myCanvas3);

// Add the parent Canvas as the Content of the Window Object
mainWindow.Content = myParentCanvas;
mainWindow.Show ();

<Page WindowTitle="Canvas Sample" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <Canvas Height="400" Width="400">
    <Canvas Height="100" Width="100" Top="0" Left="0" Background="Red"/>
    <Canvas Height="100" Width="100" Top="100" Left="100" Background="Green"/>
    <Canvas Height="100" Width="100" Top="50" Left="50" Background="Blue"/>
  </Canvas>
</Page>

L'application compilée produit une nouvelle interface utilisateur semblable à ce qui suit.

Élément Canevas classique.

DockPanel

L'élément DockPanel utilise la propriété attachée Dock pour positionner du contenu le long des extrémités d'un conteneur. Lorsque Dock a la valeur Top ou Bottom, il positionne les éléments enfants au-dessus ou en dessous les uns des autres. Lorsque Dock a la valeur Left ou Right, il positionne les éléments enfants à gauche ou à droite les uns des autres. La propriété LastChildFill détermine la position du dernier élément ajouté en tant qu'enfant de DockPanel.

Vous pouvez utiliser DockPanel pour positionner un groupe de contrôles connexes, tel qu'un ensemble de boutons. Vous pouvez également l'utiliser pour créer une interface utilisateur « en panneaux », semblable à celle de Microsoft Outlook.

Dimensionnement relatif au contenu

Si ses propriétés Height et Width ne sont pas spécifiées, DockPanel se dimensionne par rapport à son contenu. Sa taille peut augmenter ou diminuer pour s'adapter à celle de ses éléments enfants. Cependant, lorsque ces propriétés sont spécifiées et qu'il n'y a plus de place pour l'élément enfant spécifié suivant, DockPanel n'affiche pas cet élément enfant ou les éléments enfants ultérieurs, et ne mesure pas les éléments enfants ultérieurs.

LastChildFill

Par défaut, le dernier enfant d'un élément DockPanel « remplira » l'espace non alloué restant. Si ce comportement n'est pas souhaité, affectez false à la propriété LastChildFill.

Définition et utilisation de DockPanel

L'exemple suivant montre comment partitionner l'espace à l'aide de DockPanel. Cinq éléments Border sont ajoutés en tant qu'enfants d'un DockPanel parent. Chacun d'eux utilise une différente propriété de positionnement de DockPanel afin de partitionner l'espace. Le dernier élément « remplit » l'espace non alloué restant.

WindowTitle = "DockPanel Sample"
'Create a DockPanel as the root Panel
Dim myDockPanel As New DockPanel()
myDockPanel.LastChildFill = True

' Define the child content
Dim myBorder1 As New Border()
myBorder1.Height = 25
myBorder1.Background = Brushes.SkyBlue
myBorder1.BorderBrush = Brushes.Black
myBorder1.BorderThickness = New Thickness(1)
DockPanel.SetDock(myBorder1, Dock.Top)
Dim myTextBlock1 As New TextBlock()
myTextBlock1.Foreground = Brushes.Black
myTextBlock1.Text = "Dock = Top"
myBorder1.Child = myTextBlock1

Dim myBorder2 As New Border()
myBorder2.Height = 25
myBorder2.Background = Brushes.SkyBlue
myBorder2.BorderBrush = Brushes.Black
myBorder2.BorderThickness = New Thickness(1)
DockPanel.SetDock(myBorder2, Dock.Top)
Dim myTextBlock2 As New TextBlock()
myTextBlock2.Foreground = Brushes.Black
myTextBlock2.Text = "Dock = Top"
myBorder2.Child = myTextBlock2

Dim myBorder3 As New Border()
myBorder3.Height = 25
myBorder3.Background = Brushes.LemonChiffon
myBorder3.BorderBrush = Brushes.Black
myBorder3.BorderThickness = New Thickness(1)
DockPanel.SetDock(myBorder3, Dock.Bottom)
Dim myTextBlock3 As New TextBlock()
myTextBlock3.Foreground = Brushes.Black
myTextBlock3.Text = "Dock = Bottom"
myBorder3.Child = myTextBlock3

Dim myBorder4 As New Border()
myBorder4.Width = 200
myBorder4.Background = Brushes.PaleGreen
myBorder4.BorderBrush = Brushes.Black
myBorder4.BorderThickness = New Thickness(1)
DockPanel.SetDock(myBorder4, Dock.Left)
Dim myTextBlock4 As New TextBlock()
myTextBlock4.Foreground = Brushes.Black
myTextBlock4.Text = "Dock = Left"
myBorder4.Child = myTextBlock4

Dim myBorder5 As New Border()
myBorder5.Background = Brushes.White
myBorder5.BorderBrush = Brushes.Black
myBorder5.BorderThickness = New Thickness(1)
Dim myTextBlock5 As New TextBlock()
myTextBlock5.Foreground = Brushes.Black
myTextBlock5.Text = "This content will Fill the remaining space"
myBorder5.Child = myTextBlock5

' Add child elements to the DockPanel Children collection
myDockPanel.Children.Add(myBorder1)
myDockPanel.Children.Add(myBorder2)
myDockPanel.Children.Add(myBorder3)
myDockPanel.Children.Add(myBorder4)
myDockPanel.Children.Add(myBorder5)
Me.Content = myDockPanel
// Create the application's main window
mainWindow = new Window ();
mainWindow.Title = "DockPanel Sample";

// Create the DockPanel
DockPanel myDockPanel = new DockPanel();
myDockPanel.LastChildFill = true;

// Define the child content
Border myBorder1 = new Border();
myBorder1.Height = 25;
myBorder1.Background = Brushes.SkyBlue;
myBorder1.BorderBrush = Brushes.Black;
myBorder1.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder1, Dock.Top);
TextBlock myTextBlock1 = new TextBlock();
myTextBlock1.Foreground = Brushes.Black;
myTextBlock1.Text = "Dock = Top";
myBorder1.Child = myTextBlock1;

Border myBorder2 = new Border();
myBorder2.Height = 25;
myBorder2.Background = Brushes.SkyBlue;
myBorder2.BorderBrush = Brushes.Black;
myBorder2.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder2, Dock.Top);
TextBlock myTextBlock2 = new TextBlock();
myTextBlock2.Foreground = Brushes.Black;
myTextBlock2.Text = "Dock = Top";
myBorder2.Child = myTextBlock2;

Border myBorder3 = new Border();
myBorder3.Height = 25;
myBorder3.Background = Brushes.LemonChiffon;
myBorder3.BorderBrush = Brushes.Black;
myBorder3.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder3, Dock.Bottom);
TextBlock myTextBlock3 = new TextBlock();
myTextBlock3.Foreground = Brushes.Black;
myTextBlock3.Text = "Dock = Bottom";
myBorder3.Child = myTextBlock3;

Border myBorder4 = new Border();
myBorder4.Width = 200;
myBorder4.Background = Brushes.PaleGreen;
myBorder4.BorderBrush = Brushes.Black;
myBorder4.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder4, Dock.Left);
TextBlock myTextBlock4 = new TextBlock();
myTextBlock4.Foreground = Brushes.Black;
myTextBlock4.Text = "Dock = Left";
myBorder4.Child = myTextBlock4;

Border myBorder5 = new Border();
myBorder5.Background = Brushes.White;
myBorder5.BorderBrush = Brushes.Black;
myBorder5.BorderThickness = new Thickness(1);
TextBlock myTextBlock5 = new TextBlock();
myTextBlock5.Foreground = Brushes.Black;
myTextBlock5.Text = "This content will Fill the remaining space";
myBorder5.Child = myTextBlock5;


// Add child elements to the DockPanel Children collection
myDockPanel.Children.Add(myBorder1);
myDockPanel.Children.Add(myBorder2);
myDockPanel.Children.Add(myBorder3);
myDockPanel.Children.Add(myBorder4);
myDockPanel.Children.Add(myBorder5);

// Add the parent Canvas as the Content of the Window Object
mainWindow.Content = myDockPanel;
mainWindow.Show ();

<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" WindowTitle="DockPanel Sample">
  <DockPanel LastChildFill="True">
    <Border Height="25" Background="SkyBlue" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Top">
      <TextBlock Foreground="Black">Dock = "Top"</TextBlock>
    </Border>
    <Border Height="25" Background="SkyBlue" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Top">
      <TextBlock Foreground="Black">Dock = "Top"</TextBlock>
    </Border>
    <Border Height="25" Background="LemonChiffon" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Bottom">
      <TextBlock Foreground="Black">Dock = "Bottom"</TextBlock>
    </Border>
    <Border Width="200" Background="PaleGreen" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Left">
      <TextBlock Foreground="Black">Dock = "Left"</TextBlock>
    </Border>
    <Border Background="White" BorderBrush="Black" BorderThickness="1">
      <TextBlock Foreground="Black">This content will "Fill" the remaining space</TextBlock>
    </Border>
  </DockPanel>
</Page>

L'application compilée produit une nouvelle interface utilisateur semblable à ce qui suit.

Scénario DockPanel classique.

Grid

L'élément Grid réunit les fonctionnalités d'un positionnement absolu et d'un contrôle de données tabulaires. Grid vous permet de positionner facilement des éléments et de leur appliquer un style. Grid vous permet de définir des regroupements souples de lignes et de colonnes, et il fournit même un mécanisme de partage des informations de dimensionnement entre plusieurs éléments Grid.

En quoi Grid est différent de Table ?

Table et Grid partagent des fonctionnalités communes, mais chacun d'eux est plus adapté à des scénarios différents. Table est conçu pour être utilisé au sein d'un contenu de flux (consultez Vue d'ensemble des documents dynamiques pour plus d'informations sur le contenu de flux). Les grilles fonctionnent de manière optimale dans les formulaires (en général n'importe où en dehors d'un contenu de flux). Dans un FlowDocument, Table prend en charge les comportements de contenu tels que la pagination, la gestion du rendu des colonnes et la sélection de contenu, tandis que Grid ne le fait pas. Grid fonctionne en revanche de manière optimale en dehors d'un FlowDocument pour de nombreuses raisons, dont le fait que Grid ajoute des éléments basés sur un index de ligne et de colonne, alors que Table ne le fait pas. L'élément Grid permet la superposition de contenus enfants, où plusieurs éléments peuvent exister dans une même « cellule ». Table ne prend pas en charge la superposition. Les éléments enfants d'un élément Grid peuvent être positionnés de façon absolue par rapport à la zone des limites de leur « cellule ». Table ne prend pas en charge cette fonctionnalité. Enfin, Grid est un élément plus allégé que Table.

Comportement de dimensionnement de colonnes et de lignes

Les colonnes et les lignes définies dans un élément Grid peuvent tirer parti du dimensionnement Star pour distribuer proportionnellement l'espace restant. Si Star est sélectionné comme hauteur ou largeur d'une ligne ou d'une colonne, cette colonne ou cette ligne reçoit une proportion pondérée de l'espace disponible restant. Par opposition, Auto distribue l'espace de façon égale selon la taille du contenu de la colonne ou de la ligne. Cette valeur est exprimée sous la forme * ou 2* lorsque vous utilisez XAML (Extensible Application Markup Language). Dans le premier cas, la ligne ou la colonne reçoit une fois l'espace disponible, dans le second cas, elle le reçoit deux fois, et ainsi de suite. Pour plus d'informations sur le dimensionnement star, consultez l'exemple Utiliser le redimensionnement Star, exemple. En combinant cette technique pour distribuer l'espace proportionnellement avec un HorizontalAlignment et un VerticalAlignment de valeur Stretch, il est possible de partitionner l'espace de disposition selon un pourcentage de l'espace écran. Grid est le seul panneau de disposition à pouvoir ainsi distribuer l'espace.

Définition et utilisation de Grid

L'exemple suivant montre comment générer une interface utilisateur semblable à celle de la boîte de dialogue Exécuter du menu Démarrer de Windows.

'Create a Grid as the root Panel element.
Dim myGrid As New Grid()
myGrid.Height = 165
myGrid.Width = 425
myGrid.Background = Brushes.Gainsboro
myGrid.ShowGridLines = True
myGrid.HorizontalAlignment = Windows.HorizontalAlignment.Left
myGrid.VerticalAlignment = Windows.VerticalAlignment.Top

' Define and Add the Rows and Columns.
Dim colDef1 As New ColumnDefinition
colDef1.Width = New GridLength(1, GridUnitType.Auto)
Dim colDef2 As New ColumnDefinition
colDef2.Width = New GridLength(1, GridUnitType.Star)
Dim colDef3 As New ColumnDefinition
colDef3.Width = New GridLength(1, GridUnitType.Star)
Dim colDef4 As New ColumnDefinition
colDef4.Width = New GridLength(1, GridUnitType.Star)
Dim colDef5 As New ColumnDefinition
colDef5.Width = New GridLength(1, GridUnitType.Star)
myGrid.ColumnDefinitions.Add(colDef1)
myGrid.ColumnDefinitions.Add(colDef2)
myGrid.ColumnDefinitions.Add(colDef3)
myGrid.ColumnDefinitions.Add(colDef4)
myGrid.ColumnDefinitions.Add(colDef5)

Dim rowDef1 As New RowDefinition
rowDef1.Height = New GridLength(1, GridUnitType.Auto)
Dim rowDef2 As New RowDefinition
rowDef2.Height = New GridLength(1, GridUnitType.Auto)
Dim rowDef3 As New Controls.RowDefinition
rowDef3.Height = New GridLength(1, GridUnitType.Star)
Dim rowDef4 As New RowDefinition
rowDef4.Height = New GridLength(1, GridUnitType.Auto)
myGrid.RowDefinitions.Add(rowDef1)
myGrid.RowDefinitions.Add(rowDef2)
myGrid.RowDefinitions.Add(rowDef3)
myGrid.RowDefinitions.Add(rowDef4)

' Add the Image.
Dim img1 As New Image
img1.Source = New System.Windows.Media.Imaging.BitmapImage(New Uri("runicon.png", UriKind.Relative))
Grid.SetRow(img1, 0)
Grid.SetColumn(img1, 0)
myGrid.Children.Add(img1)

' Add the main application dialog.
Dim txt1 As New TextBlock
txt1.Text = "Type the name of a program, document, or Internet resource, and Windows will open it for you."
txt1.TextWrapping = TextWrapping.Wrap
Grid.SetColumnSpan(txt1, 4)
Grid.SetRow(txt1, 0)
Grid.SetColumn(txt1, 1)
myGrid.Children.Add(txt1)

' Add the second TextBlock Cell to the Grid.
Dim txt2 As New TextBlock
txt2.Text = "Open:"
Grid.SetRow(txt2, 1)
Grid.SetColumn(txt2, 0)
myGrid.Children.Add(txt2)

' Add the TextBox control.
Dim tb1 As New TextBox
Grid.SetRow(tb1, 1)
Grid.SetColumn(tb1, 1)
Grid.SetColumnSpan(tb1, 5)
myGrid.Children.Add(tb1)

' Add the Button controls.
Dim button1 As New Button
Dim button2 As New Button
Dim button3 As New Button
button1.Content = "OK"
button1.Margin = New Thickness(10, 0, 10, 15)
button2.Content = "Cancel"
button2.Margin = New Thickness(10, 0, 10, 15)
button3.Content = "Browse ..."
button3.Margin = New Thickness(10, 0, 10, 15)

Grid.SetRow(button1, 3)
Grid.SetColumn(button1, 2)
Grid.SetRow(button2, 3)
Grid.SetColumn(button2, 3)
Grid.SetRow(button3, 3)
Grid.SetColumn(button3, 4)
myGrid.Children.Add(button1)
myGrid.Children.Add(button2)
myGrid.Children.Add(button3)

Me.Content = myGrid
// Create the Grid.
grid1 = new Grid ();
grid1.Background = Brushes.Gainsboro;
grid1.HorizontalAlignment = HorizontalAlignment.Left;
grid1.VerticalAlignment = VerticalAlignment.Top;
grid1.ShowGridLines = true;
grid1.Width = 425;
grid1.Height = 165;

// Define the Columns.
colDef1 = new ColumnDefinition();
colDef1.Width = new GridLength(1, GridUnitType.Auto);
colDef2 = new ColumnDefinition();
colDef2.Width = new GridLength(1, GridUnitType.Star);
colDef3 = new ColumnDefinition();
colDef3.Width = new GridLength(1, GridUnitType.Star);
colDef4 = new ColumnDefinition();
colDef4.Width = new GridLength(1, GridUnitType.Star);
colDef5 = new ColumnDefinition();
colDef5.Width = new GridLength(1, GridUnitType.Star);
grid1.ColumnDefinitions.Add(colDef1);
grid1.ColumnDefinitions.Add(colDef2);
grid1.ColumnDefinitions.Add(colDef3);
grid1.ColumnDefinitions.Add(colDef4);
grid1.ColumnDefinitions.Add(colDef5);

// Define the Rows.
rowDef1 = new RowDefinition();
rowDef1.Height = new GridLength(1, GridUnitType.Auto);
rowDef2 = new RowDefinition();
rowDef2.Height = new GridLength(1, GridUnitType.Auto);
rowDef3 = new RowDefinition();
rowDef3.Height = new GridLength(1, GridUnitType.Star);
rowDef4 = new RowDefinition();
rowDef4.Height = new GridLength(1, GridUnitType.Auto);
grid1.RowDefinitions.Add(rowDef1);
grid1.RowDefinitions.Add(rowDef2);
grid1.RowDefinitions.Add(rowDef3);
grid1.RowDefinitions.Add(rowDef4);

// Add the Image.
img1 = new Image();
img1.Source = new System.Windows.Media.Imaging.BitmapImage(new Uri("runicon.png", UriKind.Relative));
Grid.SetRow(img1, 0);
Grid.SetColumn(img1, 0);

// Add the main application dialog.
txt1 = new TextBlock();
txt1.Text = "Type the name of a program, folder, document, or Internet resource, and Windows will open it for you.";
txt1.TextWrapping = TextWrapping.Wrap;
Grid.SetColumnSpan(txt1, 4);
Grid.SetRow(txt1, 0);
Grid.SetColumn(txt1, 1);

// Add the second text cell to the Grid.
txt2 = new TextBlock();
txt2.Text = "Open:";
Grid.SetRow(txt2, 1);
Grid.SetColumn(txt2, 0);

// Add the TextBox control.
tb1 = new TextBox();
Grid.SetRow(tb1, 1);
Grid.SetColumn(tb1, 1);
Grid.SetColumnSpan(tb1, 5);

// Add the buttons.
button1 = new Button();
button2 = new Button();
button3 = new Button();
button1.Content = "OK";
button2.Content = "Cancel";
button3.Content = "Browse ...";
Grid.SetRow(button1, 3);
Grid.SetColumn(button1, 2);
button1.Margin = new Thickness(10, 0, 10, 15);
button2.Margin = new Thickness(10, 0, 10, 15);
button3.Margin = new Thickness(10, 0, 10, 15);
Grid.SetRow(button2, 3);
Grid.SetColumn(button2, 3);
Grid.SetRow(button3, 3);
Grid.SetColumn(button3, 4);

grid1.Children.Add(img1);
grid1.Children.Add(txt1);
grid1.Children.Add(txt2);
grid1.Children.Add(tb1);
grid1.Children.Add(button1);
grid1.Children.Add(button2);
grid1.Children.Add(button3);

mainWindow.Content = grid1;
<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      WindowTitle="Grid Run Dialog Sample" 
      WindowWidth="425" 
      WindowHeight="225">
  <Grid Background="#DCDCDC"
        Width="425"
        Height="165"
        HorizontalAlignment="Left"
        VerticalAlignment="Top"
        ShowGridLines="True">
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto" />
      <ColumnDefinition Width="*" />
      <ColumnDefinition Width="*"/>
      <ColumnDefinition Width="*"/>
      <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="*" />
      <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <Image Grid.Column="0" Grid.Row="0" Source="RunIcon.png" />
    <TextBlock Grid.Column="1" Grid.ColumnSpan="4" Grid.Row="0" TextWrapping="Wrap">
      Type the name of a program, folder, document, or
      Internet resource, and Windows will open it for you.
    </TextBlock>
    <TextBlock Grid.Column="0" Grid.Row="1">Open:</TextBlock>
    <TextBox Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="5" />
    <Button Margin="10, 0, 10, 15" Grid.Row="3" Grid.Column="2">OK</Button>
    <Button Margin="10, 0, 10, 15" Grid.Row="3" Grid.Column="3">Cancel</Button>
    <Button Margin="10, 0, 10, 15" Grid.Row="3" Grid.Column="4">Browse ...</Button>
  </Grid>
</Page>

L'application compilée produit une nouvelle interface utilisateur semblable à ce qui suit.

Élément de grille classique.

StackPanel

StackPanel vous permet d'« empiler » des éléments dans un sens assigné. La direction de la pile par défaut est dans le sens vertical. La propriété Orientation peut être utilisée pour contrôler le flux du contenu.

Comparaison de StackPanel et DockPanel

Bien que DockPanel puisse aussi « empiler » des éléments enfants, DockPanel et StackPanel ne produisent pas des résultats analogues dans certains scénarios d'usage. Par exemple, l'ordre des éléments enfants peut affecter leur taille dans un DockPanel mais pas dans un StackPanel. En effet, StackPanel mesure dans le sens de l'empilement jusqu'à PositiveInfinity, tandis que DockPanel mesure uniquement la taille disponible.

L'exemple suivant illustre ces différences clés.

'Add root Grid
Dim myGrid As New Grid
myGrid.Width = 175
myGrid.Height = 150
Dim myRowDef1 As New RowDefinition
Dim myRowDef2 As New RowDefinition
myGrid.RowDefinitions.Add(myRowDef1)
myGrid.RowDefinitions.Add(myRowDef2)

'Define the DockPanel
Dim myDockPanel As New DockPanel
Grid.SetRow(myDockPanel, 0)

'Define an Image and Source.
Dim myImage As New Image
Dim bi As New BitmapImage
bi.BeginInit()
bi.UriSource = New Uri("smiley_stackpanel.png", UriKind.Relative)
bi.EndInit()
myImage.Source = bi

Dim myImage2 As New Image
Dim bi2 As New BitmapImage
bi2.BeginInit()
bi2.UriSource = New Uri("smiley_stackpanel.png", UriKind.Relative)
bi2.EndInit()
myImage2.Source = bi2

Dim myImage3 As New Image
Dim bi3 As New BitmapImage
bi3.BeginInit()
bi3.UriSource = New Uri("smiley_stackpanel.PNG", UriKind.Relative)
bi3.EndInit()
myImage3.Stretch = Stretch.Fill
myImage3.Source = bi3

'Add the images to the parent DockPanel.
myDockPanel.Children.Add(myImage)
myDockPanel.Children.Add(myImage2)
myDockPanel.Children.Add(myImage3)

'Define a StackPanel.
Dim myStackPanel As New StackPanel
myStackPanel.Orientation = Orientation.Horizontal
Grid.SetRow(myStackPanel, 1)

Dim myImage4 As New Image
Dim bi4 As New BitmapImage
bi4.BeginInit()
bi4.UriSource = New Uri("smiley_stackpanel.png", UriKind.Relative)
bi4.EndInit()
myImage4.Source = bi4

Dim myImage5 As New Image
Dim bi5 As New BitmapImage
bi5.BeginInit()
bi5.UriSource = New Uri("smiley_stackpanel.png", UriKind.Relative)
bi5.EndInit()
myImage5.Source = bi5

Dim myImage6 As New Image
Dim bi6 As New BitmapImage
bi6.BeginInit()
bi6.UriSource = New Uri("smiley_stackpanel.PNG", UriKind.Relative)
bi6.EndInit()
myImage6.Stretch = Stretch.Fill
myImage6.Source = bi6

'Add the images to the parent StackPanel.
myStackPanel.Children.Add(myImage4)
myStackPanel.Children.Add(myImage5)
myStackPanel.Children.Add(myImage6)

'Add the layout panels as children of the Grid
myGrid.Children.Add(myDockPanel)
myGrid.Children.Add(myStackPanel)

// Create the application's main window
mainWindow = new Window ();
mainWindow.Title = "StackPanel vs. DockPanel";

// Add root Grid
myGrid = new Grid();
myGrid.Width = 175;
myGrid.Height = 150;
RowDefinition myRowDef1 = new RowDefinition();
RowDefinition myRowDef2 = new RowDefinition();
myGrid.RowDefinitions.Add(myRowDef1);
myGrid.RowDefinitions.Add(myRowDef2);

// Define the DockPanel
myDockPanel = new DockPanel();
Grid.SetRow(myDockPanel, 0);

//Define an Image and Source
Image myImage = new Image();
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri("smiley_stackpanel.png", UriKind.Relative);
bi.EndInit();
myImage.Source = bi;

Image myImage2 = new Image();
BitmapImage bi2 = new BitmapImage();
bi2.BeginInit();
bi2.UriSource = new Uri("smiley_stackpanel.png", UriKind.Relative);
bi2.EndInit();
myImage2.Source = bi2;

Image myImage3 = new Image();
BitmapImage bi3 = new BitmapImage();
bi3.BeginInit();
bi3.UriSource = new Uri("smiley_stackpanel.PNG", UriKind.Relative);
bi3.EndInit();
myImage3.Stretch = Stretch.Fill;
myImage3.Source = bi3;

// Add the images to the parent DockPanel
myDockPanel.Children.Add(myImage);
myDockPanel.Children.Add(myImage2);
myDockPanel.Children.Add(myImage3);

//Define a StackPanel
myStackPanel = new StackPanel();
myStackPanel.Orientation = Orientation.Horizontal;
Grid.SetRow(myStackPanel, 1);

Image myImage4 = new Image();
BitmapImage bi4 = new BitmapImage();
bi4.BeginInit();
bi4.UriSource = new Uri("smiley_stackpanel.png", UriKind.Relative);
bi4.EndInit();
myImage4.Source = bi4;

Image myImage5 = new Image();
BitmapImage bi5 = new BitmapImage();
bi5.BeginInit();
bi5.UriSource = new Uri("smiley_stackpanel.png", UriKind.Relative);
bi5.EndInit();
myImage5.Source = bi5;

Image myImage6 = new Image();
BitmapImage bi6 = new BitmapImage();
bi6.BeginInit();
bi6.UriSource = new Uri("smiley_stackpanel.PNG", UriKind.Relative);
bi6.EndInit();
myImage6.Stretch = Stretch.Fill;
myImage6.Source = bi6;

// Add the images to the parent StackPanel
myStackPanel.Children.Add(myImage4);
myStackPanel.Children.Add(myImage5);
myStackPanel.Children.Add(myImage6);

// Add the layout panels as children of the Grid
myGrid.Children.Add(myDockPanel);
myGrid.Children.Add(myStackPanel);

// Add the Grid as the Content of the Parent Window Object
mainWindow.Content = myGrid;
mainWindow.Show ();

<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      WindowTitle="StackPanel vs. DockPanel">
  <Grid Width="175" Height="150">
    <Grid.ColumnDefinitions>
      <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition />
      <RowDefinition />
    </Grid.RowDefinitions>

    <DockPanel Grid.Column="0" Grid.Row="0">
      <Image Source="smiley_stackpanel.png" />
      <Image Source="smiley_stackpanel.png" />
      <Image Source="smiley_stackpanel.png" Stretch="Fill"/>
    </DockPanel>

    <StackPanel Grid.Column="0" Grid.Row="1"  Orientation="Horizontal">
      <Image Source="smiley_stackpanel.png" />
      <Image Source="smiley_stackpanel.png" />
      <Image Source="smiley_stackpanel.png" Stretch="Fill"/>
    </StackPanel>
    </Grid>
</Page>

La différence de comportement du rendu est illustrée sur cette image.

Capture d'écran : StackPanel et DockPanel

Définition et utilisation de StackPanel

L'exemple suivant montre comment utiliser StackPanel pour créer un ensemble de boutons positionnés dans le sens vertical. Pour définir le positionnement horizontal, affectez Horizontal à la propriété Orientation.

WindowTitle = "StackPanel Sample"
' Define the StackPanel
Dim myStackPanel As New StackPanel()
myStackPanel.HorizontalAlignment = Windows.HorizontalAlignment.Left
myStackPanel.VerticalAlignment = Windows.VerticalAlignment.Top

' Define child content
Dim myButton1 As New Button()
myButton1.Content = "Button 1"
Dim myButton2 As New Button()
myButton2.Content = "Button 2"
Dim myButton3 As New Button()
myButton3.Content = "Button 3"

' Add child elements to the parent StackPanel
myStackPanel.Children.Add(myButton1)
myStackPanel.Children.Add(myButton2)
myStackPanel.Children.Add(myButton3)

Me.Content = myStackPanel
// Create the application's main window
mainWindow = new Window ();
mainWindow.Title = "StackPanel Sample";

// Define the StackPanel
myStackPanel = new StackPanel();
myStackPanel.HorizontalAlignment = HorizontalAlignment.Left;
myStackPanel.VerticalAlignment = VerticalAlignment.Top;

// Define child content
Button myButton1 = new Button();
myButton1.Content = "Button 1";
Button myButton2 = new Button();
myButton2.Content = "Button 2";
Button myButton3 = new Button();
myButton3.Content = "Button 3";

// Add child elements to the parent StackPanel
myStackPanel.Children.Add(myButton1);
myStackPanel.Children.Add(myButton2);
myStackPanel.Children.Add(myButton3);           

// Add the StackPanel as the Content of the Parent Window Object
mainWindow.Content = myStackPanel;
mainWindow.Show ();

<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" WindowTitle="StackPanel Sample">
    <StackPanel HorizontalAlignment="Left"
                VerticalAlignment="Top">
        <Button>Button 1</Button>
        <Button>Button 2</Button>
        <Button>Button 3</Button>
    </StackPanel>
</Page>

L'application compilée produit une nouvelle interface utilisateur semblable à ce qui suit.

Élément StackPanel classique.

VirtualizingStackPanel

WPF fournit également une variante de l'élément StackPanel qui « virtualise » automatiquement du contenu enfant lié aux données. Dans ce contexte, le mot « virtualiser » fait référence à une technique par laquelle un sous-ensemble de UIElements est généré à partir d'un plus grand nombre d'éléments de données, sur la base des éléments qui sont visibles sur l'écran. Générer un grand nombre d'éléments de l'interface utilisateur, alors que seuls un certain nombre d'entre eux peuvent être visibles sur l'écran à un moment donné, provoque une utilisation intensive de la mémoire et du processeur. VirtualizingStackPanel (via les fonctionnalités fournies par VirtualizingPanel) calcule les éléments visibles et fonctionne avec ItemContainerGenerator à partir d'un ItemsControl (tel que ListBox ou ListView) afin de ne créer des UIElements que pour les éléments visibles.

L'élément VirtualizingStackPanel est automatiquement défini comme l'hôte d'éléments pour des contrôles tels que ListBox. Lors de l'hébergement d'une collection liée aux données, le contenu est automatiquement virtualisé, tant qu'il est situé dans les limites d'un ScrollViewer. Ceci améliore sensiblement les performances quand de nombreux enfants sont hébergés.

L'exemple suivant montre comment utiliser VirtualizingStackPanel comme un hôte d'éléments. La propriété attachée IsVirtualizing doit être True (par défaut) pour que la virtualisation ait lieu.

<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 est utilisé pour positionner des éléments enfants selon un ordre séquentiel de gauche à droite, en envoyant le contenu à la ligne suivante lorsqu'il atteint l'extrémité de son conteneur parent. Le contenu peut être orienté horizontalement ou verticalement. WrapPanel est utile pour les scénarios d'interface utilisateur (UI) dont le niveau de fluidité est simple. Il peut aussi être utilisé pour appliquer un dimensionnement uniforme à tous ses éléments enfants.

L'exemple suivant montre comment créer un WrapPanel pour afficher des contrôles Button qui retournent automatiquement à la ligne quand ils atteignent l'extrémité de leur conteneur.

WindowTitle = "WrapPanel Sample"

' Instantiate a new WrapPanel and set properties
Dim myWrapPanel As New WrapPanel()
myWrapPanel.Background = Brushes.Azure
myWrapPanel.Orientation = Orientation.Horizontal
myWrapPanel.ItemHeight = 25

myWrapPanel.ItemWidth = 75
myWrapPanel.Width = 150
myWrapPanel.HorizontalAlignment = Windows.HorizontalAlignment.Left
myWrapPanel.VerticalAlignment = Windows.VerticalAlignment.Top

' Define 3 button elements. Each button is sized at width of 75, so the third button wraps to the next line.
Dim btn1 As New Button()
btn1.Content = "Button 1"
Dim btn2 As New Button()
btn2.Content = "Button 2"
Dim btn3 As New Button()
btn3.Content = "Button 3"

' Add the buttons to the parent WrapPanel using the Children.Add method.
myWrapPanel.Children.Add(btn1)
myWrapPanel.Children.Add(btn2)
myWrapPanel.Children.Add(btn3)

' Add the WrapPanel to the Page as Content
Me.Content = myWrapPanel

            // Create the application's main window
            mainWindow = new System.Windows.Window();
            mainWindow.Title = "WrapPanel Sample";


            // Instantiate a new WrapPanel and set properties
            myWrapPanel = new WrapPanel();
            myWrapPanel.Background = System.Windows.Media.Brushes.Azure;
            myWrapPanel.Orientation = Orientation.Horizontal;
            myWrapPanel.ItemHeight = 25;

            myWrapPanel.ItemWidth = 75;
            myWrapPanel.Width = 150;
            myWrapPanel.HorizontalAlignment = HorizontalAlignment.Left;
            myWrapPanel.VerticalAlignment = VerticalAlignment.Top;

            // Define 3 button elements. Each button is sized at width of 75, so the third button wraps to the next line.
            btn1 = new Button();
            btn1.Content = "Button 1";
            btn2 = new Button();
            btn2.Content = "Button 2";
            btn3 = new Button();
            btn3.Content = "Button 3";

            // Add the buttons to the parent WrapPanel using the Children.Add method.
            myWrapPanel.Children.Add(btn1);
            myWrapPanel.Children.Add(btn2);
            myWrapPanel.Children.Add(btn3);

            // Add the WrapPanel to the MainWindow as Content
            mainWindow.Content = myWrapPanel;
            mainWindow.Show();

<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" WindowTitle="WrapPanel Sample">
  <Border HorizontalAlignment="Left" VerticalAlignment="Top" BorderBrush="Black" BorderThickness="2">
        <WrapPanel Background="LightBlue" Width="200" Height="100">
            <Button Width="200">Button 1</Button>
            <Button>Button 2</Button>
            <Button>Button 3</Button>
            <Button>Button 4</Button>
        </WrapPanel>
  </Border>    
</Page>

L'application compilée produit une nouvelle interface utilisateur semblable à ce qui suit.

Élément WrapPanel classique.

Éléments Panel imbriqués

Les éléments Panel peuvent être imbriqués à l'intérieur les uns des autres afin de produire des dispositions complexes. Ceci peut s'avérer très utile dans des situations où un Panel est idéal pour une partie d'une interface utilisateur, mais peut ne pas répondre aux besoins d'une autre partie de l'interface utilisateur.

Le nombre d'imbrications que votre application peut prendre en charge est illimité ; cependant, il est généralement préférable de limiter votre application uniquement aux panneaux qui sont réellement nécessaires pour la disposition souhaitée. Dans de nombreux cas, un élément Grid peut être utilisé à la place des panneaux imbriqués, du fait de sa souplesse en tant que conteneur de disposition. Cela peut accroître les performances de votre application en laissant les éléments inutiles en dehors de l'arborescence.

L'exemple suivant montre comment créer une interface utilisateur qui tire profit d'éléments imbriqués Panel pour réaliser une disposition spécifique. Dans ce cas particulier, un élément DockPanel est utilisé pour fournir la structure de l'interface utilisateur, et des éléments StackPanel imbriqués, un contrôle Grid et un Canvas sont utilisés pour positionner avec précision des éléments enfants dans le DockPanel parent.

Dim myDockPanel As New DockPanel()

Dim myBorder2 As New Border()
myBorder2.BorderThickness = New Thickness(1)
myBorder2.BorderBrush = Brushes.Black
DockPanel.SetDock(myBorder2, Dock.Left)
Dim myStackPanel As New StackPanel()
Dim myButton1 As New Button()
myButton1.Content = "Left Docked"
myButton1.Margin = New Thickness(5)
Dim myButton2 As New Button()
myButton2.Content = "StackPanel"
myButton2.Margin = New Thickness(5)
myStackPanel.Children.Add(myButton1)
myStackPanel.Children.Add(myButton2)
myBorder2.Child = myStackPanel

Dim myBorder3 As New Border()
myBorder3.BorderThickness = New Thickness(1)
myBorder3.BorderBrush = Brushes.Black
DockPanel.SetDock(myBorder3, Dock.Top)
Dim myGrid As New Grid()
myGrid.ShowGridLines = True
Dim myRowDef1 As New RowDefinition()
Dim myRowDef2 As New RowDefinition()
Dim myColDef1 As New ColumnDefinition()
Dim myColDef2 As New ColumnDefinition()
Dim myColDef3 As New ColumnDefinition()
myGrid.ColumnDefinitions.Add(myColDef1)
myGrid.ColumnDefinitions.Add(myColDef2)
myGrid.ColumnDefinitions.Add(myColDef3)
myGrid.RowDefinitions.Add(myRowDef1)
myGrid.RowDefinitions.Add(myRowDef2)
Dim myTextBlock1 As New TextBlock()
myTextBlock1.FontSize = 20
myTextBlock1.Margin = New Thickness(10)
myTextBlock1.Text = "Grid Element Docked at the Top"
Grid.SetRow(myTextBlock1, 0)
Grid.SetColumnSpan(myTextBlock1, 3)
Dim myButton3 As New Button()
myButton3.Margin = New Thickness(5)
myButton3.Content = "A Row"
Grid.SetColumn(myButton3, 0)
Grid.SetRow(myButton3, 1)
Dim myButton4 As New Button()
myButton4.Margin = New Thickness(5)
myButton4.Content = "of Button"
Grid.SetColumn(myButton4, 1)
Grid.SetRow(myButton4, 1)
Dim myButton5 As New Button()
myButton5.Margin = New Thickness(5)
myButton5.Content = "Elements"
Grid.SetColumn(myButton5, 2)
Grid.SetRow(myButton5, 1)
myGrid.Children.Add(myTextBlock1)
myGrid.Children.Add(myButton3)
myGrid.Children.Add(myButton4)
myGrid.Children.Add(myButton5)
myBorder3.Child = myGrid

Dim myBorder4 As New Border()
myBorder4.BorderBrush = Brushes.Black
myBorder4.BorderThickness = New Thickness(1)
DockPanel.SetDock(myBorder4, Dock.Bottom)
Dim myStackPanel2 As New StackPanel()
myStackPanel2.Orientation = Orientation.Horizontal
Dim myTextBlock2 As New TextBlock()
myTextBlock2.Text = "This StackPanel is Docked to the Bottom"
myTextBlock2.Margin = New Thickness(5)
myStackPanel2.Children.Add(myTextBlock2)
myBorder4.Child = myStackPanel2

Dim myBorder5 As New Border()
myBorder5.BorderBrush = Brushes.Black
myBorder5.BorderThickness = New Thickness(1)
Dim myCanvas As New Canvas()
myCanvas.ClipToBounds = True
Dim myTextBlock3 As New TextBlock()
myTextBlock3.Text = "Content in the Canvas will Fill the remaining space."
Canvas.SetTop(myTextBlock3, 50)
Canvas.SetLeft(myTextBlock3, 50)
Dim myEllipse As New Ellipse()
myEllipse.Height = 100
myEllipse.Width = 125
myEllipse.Fill = Brushes.CornflowerBlue
myEllipse.Stroke = Brushes.Aqua
Canvas.SetTop(myEllipse, 100)
Canvas.SetLeft(myEllipse, 150)
myCanvas.Children.Add(myTextBlock3)
myCanvas.Children.Add(myEllipse)
myBorder5.Child = myCanvas

myDockPanel.Children.Add(myBorder2)
myDockPanel.Children.Add(myBorder3)
myDockPanel.Children.Add(myBorder4)
myDockPanel.Children.Add(myBorder5)
// Define the DockPanel.
myDockPanel = new DockPanel();

// Add the Left Docked StackPanel
Border myBorder2 = new Border();
myBorder2.BorderThickness = new Thickness(1);
myBorder2.BorderBrush = Brushes.Black;
DockPanel.SetDock(myBorder2, Dock.Left);
StackPanel myStackPanel = new StackPanel();
Button myButton1 = new Button();
myButton1.Content = "Left Docked";
myButton1.Margin = new Thickness(5);
Button myButton2 = new Button();
myButton2.Content = "StackPanel";
myButton2.Margin = new Thickness(5);
myStackPanel.Children.Add(myButton1);
myStackPanel.Children.Add(myButton2);
myBorder2.Child = myStackPanel;

// Add the Top Docked Grid.
Border myBorder3 = new Border();
myBorder3.BorderThickness = new Thickness(1);
myBorder3.BorderBrush = Brushes.Black;
DockPanel.SetDock(myBorder3, Dock.Top);
Grid myGrid = new Grid();
myGrid.ShowGridLines = true;
RowDefinition myRowDef1 = new RowDefinition();
RowDefinition myRowDef2 = new RowDefinition();
ColumnDefinition myColDef1 = new ColumnDefinition();
ColumnDefinition myColDef2 = new ColumnDefinition();
ColumnDefinition myColDef3 = new ColumnDefinition();
myGrid.ColumnDefinitions.Add(myColDef1);
myGrid.ColumnDefinitions.Add(myColDef2);
myGrid.ColumnDefinitions.Add(myColDef3);
myGrid.RowDefinitions.Add(myRowDef1);
myGrid.RowDefinitions.Add(myRowDef2);
TextBlock myTextBlock1 = new TextBlock();
myTextBlock1.FontSize = 20;
myTextBlock1.Margin = new Thickness(10);
myTextBlock1.Text = "Grid Element Docked at the Top";
Grid.SetRow(myTextBlock1, 0);
Grid.SetColumnSpan(myTextBlock1, 3);
Button myButton3 = new Button();
myButton3.Margin = new Thickness(5);
myButton3.Content = "A Row";
Grid.SetColumn(myButton3, 0);
Grid.SetRow(myButton3, 1);
Button myButton4 = new Button();
myButton4.Margin = new Thickness(5);
myButton4.Content = "of Button";
Grid.SetColumn(myButton4, 1);
Grid.SetRow(myButton4, 1);
Button myButton5 = new Button();
myButton5.Margin = new Thickness(5);
myButton5.Content = "Elements";
Grid.SetColumn(myButton5, 2);
Grid.SetRow(myButton5, 1);
myGrid.Children.Add(myTextBlock1);
myGrid.Children.Add(myButton3);
myGrid.Children.Add(myButton4);
myGrid.Children.Add(myButton5);
myBorder3.Child = myGrid;

// Add the Bottom Docked StackPanel.
Border myBorder4 = new Border();
myBorder4.BorderBrush = Brushes.Black;
myBorder4.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder4, Dock.Bottom);
StackPanel myStackPanel2 = new StackPanel();
myStackPanel2.Orientation = Orientation.Horizontal;
TextBlock myTextBlock2 = new TextBlock();
myTextBlock2.Text = "This StackPanel is Docked to the Bottom";
myTextBlock2.Margin = new Thickness(5);
myStackPanel2.Children.Add(myTextBlock2);
myBorder4.Child = myStackPanel2;

// Add the Canvas, that fills remaining space.
Border myBorder5 = new Border();
myBorder4.BorderBrush = Brushes.Black;
myBorder5.BorderThickness = new Thickness(1);
Canvas myCanvas = new Canvas();
myCanvas.ClipToBounds = true;
TextBlock myTextBlock3 = new TextBlock();
myTextBlock3.Text = "Content in the Canvas will Fill the remaining space.";
Canvas.SetTop(myTextBlock3, 50);
Canvas.SetLeft(myTextBlock3, 50);
Ellipse myEllipse = new Ellipse();
myEllipse.Height = 100;
myEllipse.Width = 125;
myEllipse.Fill = Brushes.CornflowerBlue;
myEllipse.Stroke = Brushes.Aqua;
Canvas.SetTop(myEllipse, 100);
Canvas.SetLeft(myEllipse, 150);
myCanvas.Children.Add(myTextBlock3);
myCanvas.Children.Add(myEllipse);
myBorder5.Child = myCanvas;

// Add child elements to the parent DockPanel.
myDockPanel.Children.Add(myBorder2);
myDockPanel.Children.Add(myBorder3);
myDockPanel.Children.Add(myBorder4);
myDockPanel.Children.Add(myBorder5);
<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" WindowTitle="Nested Panels">
  <Border Background="AliceBlue" 
          Width="400" 
          Height="300" 
          BorderBrush="DarkSlateBlue" 
          BorderThickness="2"
          HorizontalAlignment="Left" 
          VerticalAlignment="Top">
    <DockPanel>
      <Border BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Left">
        <StackPanel>
          <Button Margin="5">Left Docked</Button>
          <Button Margin="5">StackPanel</Button>
        </StackPanel>
      </Border>
      <Border BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Top">
        <Grid ShowGridLines="True">
          <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
          </Grid.RowDefinitions>
          <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
          </Grid.ColumnDefinitions>
          <TextBlock FontSize="20" Margin="10" Grid.ColumnSpan="3" Grid.Row="0">Grid Element Docked to the Top.</TextBlock>
          <Button Grid.Row="1" Grid.Column="0" Margin="5">A Row</Button>
          <Button Grid.Row="1" Grid.Column="1" Margin="5">of Button</Button>
          <Button Grid.Row="1" Grid.Column="2" Margin="5">Elements</Button>
        </Grid>
      </Border>
      <Border BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Bottom">
        <StackPanel Orientation="Horizontal">
          <TextBlock Margin="5">This StackPanel is Docked to the Bottom.</TextBlock>
        </StackPanel>
      </Border>
      <Border BorderBrush="Black" BorderThickness="1">
        <Canvas ClipToBounds="True">
          <TextBlock Canvas.Top="50" Canvas.Left="50">
            Content in the Canvas will Fill the remaining Space.
          </TextBlock>
          <Ellipse Height="100" Width="125" Fill="CornflowerBlue" Stroke="Aqua" Canvas.Top="100" Canvas.Left="150"/>
        </Canvas>
      </Border>
    </DockPanel>
  </Border>
</Page>

L'application compilée produit une nouvelle interface utilisateur semblable à ce qui suit.

Interface utilisateur bénéficiant de volets imbriqués.

Éléments Panel personnalisés

WPF fournit un ensemble de contrôles de disposition souples, mais il est également possible de réaliser des comportements de disposition personnalisés en substituant les méthodes ArrangeOverride et MeasureOverride. Il est possible d'effectuer un dimensionnement et un positionnement personnalisés en définissant de nouveaux comportements de disposition dans ces méthodes override.

De même, des comportements de disposition personnalisés basés sur des classes dérivées (telles que Canvas ou Grid) peuvent être définis en substituant leurs méthodes ArrangeOverride et MeasureOverride.

L'exemple de code suivant montre comment créer un élément Panel personnalisé en C#. Ce nouveau Panel, défini comme un PlotPanel, prend en charge le positionnement d'éléments enfants qui utilise des coordonnées x et y codées en dur. Dans cet exemple, un élément Rectangle (non affiché) est positionné au point de coordonnées 50 (x), et 50 (y).

Public Class PlotPanel
    Inherits Panel
    'Override the default Measure method of Panel.

    Protected Overrides Function MeasureOverride(ByVal availableSize As System.Windows.Size) As System.Windows.Size
        Dim childSize As Size = CType(availableSize, Size)
        For Each child As UIElement In InternalChildren
            child.Measure(childSize)
        Next
        Return MyBase.MeasureOverride(availableSize)
    End Function
    Protected Overrides Function ArrangeOverride(ByVal finalSize As System.Windows.Size) As System.Windows.Size
        For Each child As UIElement In InternalChildren
            Dim x As Double = 50
            Dim y As Double = 50
            child.Arrange(New Rect(New System.Windows.Point(x, y), child.DesiredSize))
        Next
        Return MyBase.ArrangeOverride(finalSize)
    End Function
End Class
public class PlotPanel : Panel
{
    // Default public constructor
    public PlotPanel()
        : base()
    {
    }

    // Override the default Measure method of Panel
    protected override Size MeasureOverride(Size availableSize)
    {
        Size panelDesiredSize = new Size();

        // In our example, we just have one child. 
        // Report that our panel requires just the size of its only child.
        foreach (UIElement child in InternalChildren)
        {
            child.Measure(availableSize);
            panelDesiredSize = child.DesiredSize;
        }

        return panelDesiredSize ;
    }
    protected override Size ArrangeOverride(Size finalSize)
    {
        foreach (UIElement child in InternalChildren)
        {
            double x = 50;
            double y = 50;

            child.Arrange(new Rect(new Point(x, y), child.DesiredSize));
        }
        return finalSize; // Returns the final Arranged size
    }
}

Pour afficher l'exemple complet, consultez Créer un panneau personnalisé simple, exemple.

Pour afficher une implémentation de panneau plus complexe, consultez Créer un panneau d'habillage du contenu personnalisé, exemple.

Prise en charge de la localisation/globalisation

WPF prend en charge un nombre de fonctionnalités qui facilitent la création d'une interface utilisateur localisable.

Tous les éléments Panel prennent en charge en mode natif la propriété FlowDirection, qui peut être utilisée pour réorienter dynamiquement du contenu selon les paramètres régionaux de l'utilisateur ou les paramètres de langue. Pour plus d'informations, consultez FlowDirection.

La propriété SizeToContent fournit un mécanisme qui permet aux développeurs d'applications d'anticiper les besoins d'une interface utilisateur localisée. En utilisant la valeur WidthAndHeight de cette propriété, une Window parent est toujours dimensionnée dynamiquement afin de s'adapter à son contenu et n'est pas soumise à des restrictions artificielles de sa hauteur et de sa largeur.

DockPanel, Grid et StackPanel sont tous appropriés pour une interface utilisateur localisable. Canvas n'est cependant pas un bon choix, parce qu'il positionne le contenu de manière absolue, rendant ainsi difficile sa localisation.

Pour plus d'informations sur la création d'applications WPF avec des interfaces utilisateur (UI) localisables, consultez Vue d'ensemble de l'utilisation de la disposition automatique.

Voir aussi

Tâches

Galerie de dispositions WPF, exemple

Galerie de contrôles WPF, exemple

Créer un panneau d'habillage du contenu personnalisé, exemple

Concepts

Mise en route de Windows Presentation Foundation

Système de disposition

Vue d'ensemble de l'alignement, des marges et du remplissage

Vue d'ensemble des propriétés attachées

Vue d'ensemble de l'utilisation de la disposition automatique

Optimisation des performances : disposition et conception