Vue d'ensemble de Panel
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 sont utilisés pour positionner et organiser les éléments en Extensible Application Markup Language (XAML).
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'user interface (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.
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 entre les limites d'un élément Panel dérivé avec un Brush. Children représente la collection enfant d'éléments dont Panel est composé. InternalChildren représente le contenu de la collection Children plus les membres générés par la liaison de données. Tous deux consistent en une UIElementCollection d'éléments enfants hébergés dans le Panel parent.
Le Panel expose également une propriété Panel.ZIndex jointe 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 Panel.ZIndex est supérieure apparaissent en face de ceux dont la valeur Panel.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 jointes
Les éléments Panel dérivés utilisent très souvent des propriétés jointes. Une propriété jointe 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 jointes ont une syntaxe spécialisée en Extensible Application Markup Language (XAML), ce qui est montré dans plusieurs des exemples suivants.
L'un des objectifs d'une propriété jointe 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'user interface (UI), ce qui est extrêmement utile pour la disposition d'application. Pour plus d'informations, consultez Vue d'ensemble des propriétés jointes.
É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 UI 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 |
---|---|---|
Oui |
Définit une zone dans laquelle vous pouvez positionner explicitement des éléments enfants par leurs coordonnées relatives à la zone du Canvas. |
|
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. |
|
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. |
|
Oui |
Réorganise des éléments enfants sur une seule ligne pouvant être orientée horizontalement ou verticalement. |
|
Non |
Gère la disposition de boutons d'onglet dans un TabControl. |
|
Non |
Réorganise le contenu dans un contrôle ToolBar. |
|
Non |
UniformGrid est utilisé pour réorganiser des enfants dans une grille dont les cellules sont toutes de même taille. |
|
Non |
Fournit une classe de base pour des panneaux qui peuvent « virtualiser » leur collection d'enfants. |
|
Oui |
Réorganise et virtualise le contenu sur une seule ligne orientée horizontalement ou verticalement. |
|
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'UI : 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 |
---|---|---|
Limité au contenu |
Limité au contenu |
|
Limité |
Limité |
|
StackPanel (orientation verticale) |
Limité |
Limité au contenu |
StackPanel (orientation horizontale) |
Limité au contenu |
Limité |
Limité |
Limité, sauf dans les cas où Auto s'applique aux lignes et aux colonnes |
|
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 jointes, Canvas.Left, Canvas.Top, Canvas.Right et Canvas.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. Canvas est détouré à sa taille. Canvas est le seul élément de disposition qui autorise des enfants à être dessiné à l'extérieur 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 Extensible Application Markup Language (XAML) 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 de son angle supérieur gauche (x, y) est spécifiée sous la forme (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 UI semblable à ce qui suit.
DockPanel
L'élément DockPanel utilise la propriété jointe DockPanel.Dock comme jeu dans les éléments de contenu enfants pour positionner le contenu le long des bords d'un conteneur. Lorsque DockPanel.Dock a la valeur Top ou Bottom, il positionne les éléments enfants au-dessus ou en dessous les uns des autres. Lorsque DockPanel.Dock a la valeur Left ou Right, il positionne les éléments enfants à gauche ou à droite l'un de l'autre. 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 UI « 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 ();
// 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();
<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 UI semblable à ce qui suit.
Grille
L'élément Grid réunit les fonctionnalités d'un positionnement absolu et d'un contrôle de données tabulaires. Un Grid permet de positionner et mettre en forme les éléments. Grid permet de définir des regroupements de colonnes et de lignes flexibles et fournit même un mécanisme pour partager des informations de redimensionnement 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 contenu enfant, 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 Grid peuvent être positionnés de manière absolue par rapport à la zone de leurs limites de « cellule ». Table ne prend pas en charge cette fonctionnalité. Enfin, Grid est un élément plus léger 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 Extensible Application Markup Language (XAML). 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. En combinant cette technique de répartition proportionnelle de l'espace avec une valeur HorizontalAlignment et VerticalAlignment de Stretch, il est possible de partitionner l'espace de disposition en pourcentage de l'espace d'écran. Grid est le seul panneau de disposition qui peut distribuer l'espace de cette manière.
Définition et utilisation de Grid
L'exemple suivant montre comment générer une UI 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 UI semblable à ce qui suit.
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.
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 ();
// 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();
<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.
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 UI semblable à ce qui suit.
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 d'éléments 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 la fonctionnalité fournie par VirtualizingPanel) calcule les éléments visibles et utilise ItemContainerGenerator à partir d'un ItemsControl (tel que ListBox ou ListView) pour créer uniquement des éléments pour des é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é jointe VirtualizingStackPanel.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'user interface (UI) simples. 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.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
// 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();
// 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();
<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 UI semblable à ce qui suit.
É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 UI, mais peut ne pas répondre aux besoins d'une autre partie de l'UI.
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 UI 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'UI, 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 UI semblable à ce qui suit.
É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é. Ce nouveau Panel défini en tant que PlotPanel prend en charge le positionnement des éléments enfants via l'utilisation de 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 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
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:
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;
};
};
Pour voir une implémentation de panneau personnalisé 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 UI 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 UI 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 des choix adéquats pour une UIlocalisable. Canvas n'est pas un choix approprié, car il positionne le contenu de façon absolue, le rendant difficile à localiser.
Pour plus d'informations sur la création d'applications WPF avec des user interfaces (UIs) localisables, consultez Vue d'ensemble de l'utilisation de la disposition automatique.
Voir aussi
Concepts
Procédure pas à pas : mise en route de WPF
Vue d'ensemble de l'alignement, des marges et du remplissage
Vue d'ensemble des propriétés jointes
Vue d'ensemble de l'utilisation de la disposition automatique
Optimisation des performances : disposition et conception
Autres ressources
Galerie de dispositions WPF, exemple (page éventuellement en anglais)
Galerie de contrôles WPF, exemple (page éventuellement en anglais)
Créer un panneau d'habillage du contenu personnalisé, exemple (page éventuellement en anglais)
Historique des modifications
Date |
Historique |
Motif |
---|---|---|
Juillet 2010 |
Exemple de la section « WrapPanel » corrigé. |
Commentaires client. |