Partager via


Mise en page

Cette rubrique décrit le système de disposition Windows Presentation Foundation (WPF). Comprendre comment et quand des calculs de disposition se produisent est essentiel pour la création d’interfaces utilisateur dans WPF.

Cette rubrique contient les sections suivantes :

Cadres englobants d’élément

Lorsque vous pensez à la disposition dans WPF, il est important de comprendre le cadre englobant qui entoure tous les éléments. Chaque FrameworkElement consommé par le système de mise en page peut être considéré comme un rectangle qui s'insère dans la mise en page. La classe LayoutInformation retourne les limites de l’allocation de disposition ou de l’emplacement d’un élément. La taille du rectangle est déterminée en calculant l’espace d’écran disponible, la taille des contraintes, les propriétés spécifiques à la disposition (telles que la marge et le remplissage) et le comportement individuel de l’élément Panel parent. En traitant ces données, le système de mise en page peut calculer la position de tous les enfants d'un Panelparticulier. Il est important de se rappeler que les caractéristiques de dimensionnement définies au niveau de l’élément parent, telles que Border, affectent ses enfants.

L’illustration suivante montre une disposition simple.

Capture d’écran montrant une grille classique, aucune zone englobante superposée.

Cette disposition peut être obtenue à l’aide du code XAML suivant.

<Grid Name="myGrid" Background="LightSteelBlue" Height="150">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="250"/>
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition />
    <RowDefinition />
  </Grid.RowDefinitions>
  <TextBlock Name="txt1" Margin="5" FontSize="16" FontFamily="Verdana" Grid.Column="0" Grid.Row="0">Hello World!</TextBlock>
  <Button Click="getLayoutSlot1" Width="125" Height="25" Grid.Column="0" Grid.Row="1">Show Bounding Box</Button>
  <TextBlock Name="txt2" Grid.Column="1" Grid.Row="2"/>
</Grid>

Un élément TextBlock unique est hébergé dans un Grid. Alors que le texte remplit uniquement le coin supérieur gauche de la première colonne, l’espace alloué pour l'TextBlock est réellement beaucoup plus grand. Le cadre englobant de n’importe quel FrameworkElement peut être récupéré en utilisant la méthode GetLayoutSlot. L’illustration suivante montre le cadre englobant de l’élément TextBlock.

Capture d’écran montrant que la zone englobante TextBlock est désormais visible.

Comme le montre le rectangle jaune, l’espace alloué pour l’élément TextBlock est en fait beaucoup plus grand qu’il n’apparaît. À mesure que des éléments supplémentaires sont ajoutés à la Grid, cette allocation peut diminuer ou augmenter, en fonction du type et de la taille des éléments qui sont ajoutés.

L’emplacement de disposition du TextBlock est traduit en Path à l’aide de la méthode GetLayoutSlot. Cette technique peut s’avérer utile pour afficher le cadre englobant d’un élément.

private void getLayoutSlot1(object sender, System.Windows.RoutedEventArgs e)
{
    RectangleGeometry myRectangleGeometry = new RectangleGeometry();
    myRectangleGeometry.Rect = LayoutInformation.GetLayoutSlot(txt1);
    Path myPath = new Path();
    myPath.Data = myRectangleGeometry;
    myPath.Stroke = Brushes.LightGoldenrodYellow;
    myPath.StrokeThickness = 5;
    Grid.SetColumn(myPath, 0);
    Grid.SetRow(myPath, 0);
    myGrid.Children.Add(myPath);
    txt2.Text = "LayoutSlot is equal to " + LayoutInformation.GetLayoutSlot(txt1).ToString();
}
Private Sub getLayoutSlot1(ByVal sender As Object, ByVal e As RoutedEventArgs)
    Dim myRectangleGeometry As New RectangleGeometry
    myRectangleGeometry.Rect = LayoutInformation.GetLayoutSlot(txt1)
    Dim myPath As New Path
    myPath.Data = myRectangleGeometry
    myPath.Stroke = Brushes.LightGoldenrodYellow
    myPath.StrokeThickness = 5
    Grid.SetColumn(myPath, 0)
    Grid.SetRow(myPath, 0)
    myGrid.Children.Add(myPath)
    txt2.Text = "LayoutSlot is equal to " + LayoutInformation.GetLayoutSlot(txt1).ToString()
End Sub

Système de disposition

À son plus simple, la disposition est un système récursif qui conduit à un élément dimensionné, positionné et dessiné. Plus précisément, la disposition décrit le processus de mesure et d’organisation des membres de la collection Children de l'élément Panel. La disposition est un processus intensif. Plus la collection Children est grande, plus le nombre de calculs doit être effectué. La complexité peut également être introduite en fonction du comportement de disposition défini par l’élément Panel propriétaire de la collection. Une Panelrelativement simple, telle que Canvas, peut avoir beaucoup plus de performances qu’une Panelplus complexe, telle que Grid.

Chaque fois qu’un UIElement enfant change de position, il peut potentiellement déclencher une nouvelle passe via le système de disposition. Par conséquent, il est important de comprendre les événements qui peuvent appeler le système de disposition, car les appels inutiles peuvent entraîner des performances d’application médiocres. L’exemple suivant décrit le processus qui se produit lorsque le système de disposition est appelé.

  1. Un UIElement enfant débute le processus de disposition en faisant d’abord mesurer ses propriétés de base.

  2. Les propriétés de dimensionnement définies sur FrameworkElement sont évaluées, telles que Width, Heightet Margin.

  3. une logique spécifique à Panelest appliquée, telle que la direction Dock ou l’empilage Orientation.

  4. Le contenu est organisé après que tous les enfants aient été mesurés.

  5. La collection Children est dessinée à l’écran.

  6. Le processus est appelé à nouveau si des Children supplémentaires sont ajoutées à la collection, qu’une LayoutTransform est appliquée ou que la méthode UpdateLayout est appelée.

Ce processus et la façon dont il est appelé sont définis plus en détail dans les sections suivantes.

Mesurer et disposer les enfants

Le système de disposition effectue deux passes pour chaque membre de la collection Children, une passe de mesure et une passe de réorganisation. Chaque enfant Panel fournit ses propres méthodes MeasureOverride et ArrangeOverride pour obtenir son propre comportement de disposition.

Lors de la passe de mesure, chaque membre de la collection Children est évalué. Le processus commence par un appel à la méthode Measure. Cette méthode est appelée dans l’implémentation de l’élément Panel parent et n’a pas besoin d’être appelée explicitement pour que la disposition se produise.

Premièrement, les propriétés de taille native de la UIElement sont évaluées, par exemple Clip et Visibility. Cela génère une valeur nommée constraintSize passée à MeasureCore.

Deuxièmement, les propriétés de framework définies sur FrameworkElement sont traitées, ce qui affecte la valeur de constraintSize. Ces propriétés décrivent généralement les caractéristiques de dimensionnement du UIElementsous-jacent, telles que son Height, son Width, Marginet Style. Chacune de ces propriétés peut modifier l’espace nécessaire pour afficher l’élément. MeasureOverride est ensuite appelée avec constraintSize en tant que paramètre.

Note

Il existe une différence entre les propriétés de Height et de Width et les ActualHeight et ActualWidth. Par exemple, la propriété ActualHeight est une valeur calculée basée sur d’autres entrées de hauteur et le système de disposition. La valeur est définie par le système de disposition lui-même, en fonction d’une passe de rendu réelle, et peut donc être légèrement en retard sur la valeur définie pour des propriétés, telles que Height, qui servent de base à la modification de l'entrée.

Étant donné que ActualHeight est une valeur calculée, vous devez savoir qu’il peut y avoir plusieurs modifications signalées de manière incrémentielle en raison de diverses opérations effectuées par le système de mise en page. Le système de disposition peut calculer l’espace de mesure requis pour les éléments enfants, les contraintes imposées par l’élément parent, et ainsi de suite.

L’objectif ultime de la passe de mesure est que l’enfant détermine son DesiredSize, ce qui se produit lors de l’appel MeasureCore. La valeur DesiredSize est stockée par Measure pour être utilisée pendant l'étape d'organisation du contenu.

La phase de réorganisation commence par un appel à la méthode Arrange. Pendant la passe de réorganisation, l’élément Panel parent génère un rectangle qui représente les limites de l’enfant. Cette valeur est transmise à la méthode ArrangeCore pour le traitement.

La méthode ArrangeCore évalue le DesiredSize de l’enfant et évalue les marges supplémentaires qui pourraient influencer la taille rendue de l’élément. ArrangeCore génère une arrangeSize, qui est passée comme paramètre à la méthode ArrangeOverride de l'Panel. ArrangeOverride génère le finalSize de l’enfant. Enfin, la méthode ArrangeCore effectue une dernière évaluation des propriétés de décalage, telles que la marge et l’alignement, et place l’enfant dans son emplacement de disposition. L'enfant n'a pas à remplir tout l'espace alloué, et souvent, il ne le fait pas. Le contrôle est ensuite retourné au Panel parent et le processus de disposition est terminé.

Éléments de panneau et comportements de disposition personnalisés

WPF inclut un groupe d’éléments dérivés de Panel. Ces éléments Panel permettent de nombreuses dispositions complexes. Par exemple, les éléments empilés peuvent facilement être obtenus à l’aide de l’élément StackPanel, tandis que des dispositions plus complexes et libres sont possibles à l’aide d’un Canvas.

Le tableau suivant récapitule les éléments de disposition disponibles Panel.

Nom du panneau Description
Canvas Définit une zone dans laquelle vous pouvez positionner explicitement les éléments enfants en utilisant des coordonnées par rapport à la zone Canvas.
DockPanel Définit une zone dans laquelle vous pouvez organiser des éléments enfants horizontalement ou verticalement, les uns par rapport aux autres.
Grid Définit une zone de grille flexible qui se compose de colonnes et de lignes.
StackPanel Dispose des éléments enfants sur une seule ligne orientée horizontalement ou verticalement.
VirtualizingPanel Fournit une infrastructure pour les éléments Panel qui virtualisent leur collection de données enfants. Il s’agit d’une classe abstraite.
WrapPanel Positionne des éléments enfants dans un ordre séquentiel de gauche à droite, en faisant passer le contenu à la ligne suivante au bord de la zone conteneur. L’ordre suivant se produit de manière séquentielle de haut en bas ou de droite à gauche, en fonction de la valeur de la propriété Orientation.

Pour les applications qui nécessitent une disposition qui n’est pas possible à l’aide d’un des éléments Panel prédéfinis, les comportements de disposition personnalisés peuvent être obtenus en héritent de Panel et en substituant les méthodes MeasureOverride et ArrangeOverride.

Considérations sur les performances de disposition

La disposition est un processus récursif. Chaque élément enfant d’une collection Children est traité pendant chaque appel du système de disposition. Par conséquent, le déclenchement du système de disposition doit être évité lorsqu’il n’est pas nécessaire. Les considérations suivantes peuvent vous aider à obtenir de meilleures performances.

  • Soyez conscient de quelles modifications de valeurs de propriété entraîneront une réactualisation récursive par le système de mise en page.

    Les propriétés de dépendance dont les valeurs peuvent entraîner l’initialisation du système de disposition sont marquées avec des indicateurs publics. AffectsMeasure et AffectsArrange fournissent des indices utiles sur les modifications de valeur de propriété qui forcent une mise à jour récursive par le système de disposition. En règle générale, une propriété qui peut affecter la taille du cadre englobant d’un élément doit avoir un indicateur AffectsMeasure défini avec la valeur true. Pour plus d’informations, consultez Vue d’ensemble des propriétés de dépendance.

  • Si possible, utilisez un RenderTransform au lieu d’un LayoutTransform.

    Un LayoutTransform peut être un moyen très utile d’affecter le contenu d’une interface utilisateur. Toutefois, si l’effet de la transformation n’a pas d’impact sur la position d’autres éléments, il est préférable d’utiliser un RenderTransform à la place, car RenderTransform n’appelle pas le système de disposition. LayoutTransform applique sa transformation et force une mise à jour de disposition récursive pour tenir compte de la nouvelle position de l’élément affecté.

  • Évitez les appels inutiles à UpdateLayout.

    La méthode UpdateLayout force une mise à jour de disposition récursive et n’est fréquemment pas nécessaire. Sauf si vous êtes sûr qu'une mise à jour complète est requise, utilisez le système de mise en page afin d'appeler cette méthode automatiquement.

  • Lorsque vous utilisez une collection Children volumineuse, envisagez d’utiliser un VirtualizingStackPanel au lieu d’une StackPanelrégulière.

    En virtualisant la collection enfant, le VirtualizingStackPanel conserve uniquement les objets en mémoire qui se trouvent actuellement dans le ViewPort du parent. Par conséquent, les performances sont considérablement améliorées dans la plupart des scénarios.

Rendu d’une précision inférieure au pixel et arrondi de disposition

Le système graphique WPF utilise des unités indépendantes des appareils pour permettre la résolution et l’indépendance de l’appareil. Chaque pixel indépendant de l’appareil s’ajuste automatiquement au paramètre points par pouce (ppp) du système. Cela permet aux applications WPF de s’ajuster correctement aux différents paramètres ppp et de prendre automatiquement en charge le points par pouce.

Cependant, cette indépendance ppp peut générer un rendu irrégulier des bords en raison de l’anticrénelage. Ces artefacts, souvent visibles comme des bords flous ou semi-transparents, peuvent se produire lorsque la position d’un bord se situe au milieu d’un pixel d’appareil au lieu d’entre des pixels d’appareil. Le système de disposition permet d’y remédier grâce à l’arrondi de disposition. L’arrondi de disposition intervient quand le système de disposition arrondit des valeurs de pixel non intégrales pendant la passe de disposition.

L’arrondi de disposition est désactivé par défaut. Pour activer l’arrondi de disposition, définissez la propriété UseLayoutRounding sur true pour n’importe quel FrameworkElement. Étant donné qu’il s’agit d’une propriété de dépendance, la valeur se propage à tous les enfants de l’arborescence visuelle. Pour activer l'arrondi de disposition pour l'ensemble de l'interface utilisateur, définissez UseLayoutRounding sur true sur le conteneur racine. Pour obtenir un exemple, consultez UseLayoutRounding.

Nouveautés suivantes

Comprendre comment les éléments sont mesurés et organisés est la première étape de la compréhension de la disposition. Pour plus d’informations sur les éléments Panel disponibles, consultez Vue d’ensemble des panneaux. Pour mieux comprendre les différentes propriétés de positionnement qui peuvent affecter la disposition, consultez Vue d’ensemble de l’alignement, des marges et du remplissage. Lorsque vous êtes prêt à tout assembler dans une application légère, consultez Guide : Ma première application de bureau WPF.

Voir aussi