Disposition

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 :

Zones englobantes d’élément

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

L’illustration suivante représente une disposition simple.

Screenshot that shows a typical grid, no bounding box superimposed.

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 seul TextBlock élément est hébergé dans un Grid. Bien que le texte ne remplit que l’angle supérieur gauche de la première colonne, l’espace alloué pour le texte TextBlock est réellement beaucoup plus grand. Le cadre englobant de n’importe lequel FrameworkElement peut être récupéré à l’aide de la GetLayoutSlot méthode. L’illustration suivante montre le cadre englobant de l’élément TextBlock .

Screenshot that shows that the TextBlock bounding box is now 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 à l’allocation Grid, cette allocation peut réduire ou développer, en fonction du type et de la taille des éléments ajoutés.

L’emplacement de disposition du fichier TextBlock est traduit en une Path à l’aide de la GetLayoutSlot méthode. Cette technique peut s’avérer utile pour afficher la zone englobante 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

Pour schématiser, une disposition est un système récursif qui conduit au dimensionnement, au positionnement et au tracé d’un élément. Plus précisément, la disposition décrit le processus de mesure et d’organisation des membres de la Children collection d’un Panel élément. La disposition est un processus intensif. Plus la Children collection est grande, plus le nombre de calculs doit être élevé. La complexité peut également être introduite en fonction du comportement de disposition défini par l’élément Panel propriétaire de la collection. Un niveau de performance relativement simple Panel, tel que Canvas, peut avoir beaucoup mieux de performances qu’un plus complexe Panel, tel que Grid.

Chaque fois qu’un enfant UIElement change de position, il a le potentiel de déclencher une nouvelle passe par le système de disposition. Par conséquent, il est important de comprendre quels sont les événements qui peuvent appeler le système de disposition, car un appel inutile peut nuire aux performances de l’application. Le processus suivant décrit ce qui se produit quand le système de disposition est appelé.

  1. Un enfant UIElement commence le processus de disposition en ayant d’abord ses propriétés principales mesurées.

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

  3. PanelUne logique spécifique est appliquée, telle que Dock la direction ou l’empilement Orientation.

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

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

  6. Le processus est appelé à nouveau si des éléments supplémentaires Children sont ajoutés à la collection, un LayoutTransform est appliqué ou la UpdateLayout méthode est appelée.

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

Mesure et réorganisation d’enfants

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

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

Tout d’abord, les propriétés de taille native du fichier UIElement sont évaluées, telles que Clip et Visibility. Cela génère une valeur nommée constraintSize qui est 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 sous-jacent UIElement, telles que son Height, Width, Marginet Style. Chacune de ces propriétés peut changer l’espace nécessaire à l’affichage de l’élément. MeasureOverride est ensuite appelé avec constraintSize comme paramètre.

Remarque

Il existe une différence entre les propriétés de Height et Width et ActualHeight et ActualWidth. Par exemple, la ActualHeight propriété 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 se retarder légèrement derrière la valeur définie des propriétés, telles que Height, qui sont la base du changement d’entrée.

Étant donné ActualHeight qu’il s’agit d’une valeur calculée, vous devez savoir qu’il peut y avoir plusieurs modifications signalées ou incrémentielles en raison de diverses opérations effectuées par le système de disposition. Celui-ci peut en effet calculer l’espace de mesure requis pour les éléments enfants, les contraintes de l’élément parent, et ainsi de suite.

L’objectif ultime de la passe de mesure est que l’enfant détermine son DesiredSize, qui se produit pendant l’appel MeasureCore . La DesiredSize valeur est stockée à Measure des fins d’utilisation pendant la passe d’organisation de contenu.

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

La ArrangeCore méthode évalue l’enfant DesiredSize et évalue toutes les marges supplémentaires qui peuvent affecter la taille rendue de l’élément. ArrangeCore génère un arrangeSize, qui est passé à la méthode de l’objet ArrangeOverridePanel en tant que paramètre. ArrangeOverride génère l’enfant finalSize . Enfin, la ArrangeCore méthode effectue une évaluation finale 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 besoin de remplir intégralement l’espace alloué (et souvent ne le remplit pas). Le contrôle est ensuite retourné au parent Panel et le processus de disposition est terminé.

Comportements des éléments de panneau et de disposition personnalisée

WPF inclut un groupe d’éléments dérivés de Panel. Ces Panel éléments permettent de nombreuses dispositions complexes. Par exemple, l’empilement d’éléments peut facilement être obtenu à 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 Panel disponibles.

Nom du panneau Description
Canvas Définit une zone dans laquelle vous pouvez positionner explicitement les éléments enfants en coordonnées par rapport à la Canvas zone.
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 composée 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 Panel les éléments qui virtualisent leur collecte de données enfant. 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 Orientation propriété.

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

Considérations sur les performances de disposition

La disposition est un processus récursif. Chaque élément enfant d’une Children collection est traité pendant chaque appel du système de disposition. Par conséquent, il est préférable d’éviter de déclencher le système de disposition quand cela n’est pas nécessaire. Les considérations suivantes peuvent vous aider à bénéficier de meilleures performances.

  • Identifiez les changements de valeurs de propriétés qui forceront le système de disposition à procéder à une mise à jour récursive.

    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 fournissez 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, toute propriété pouvant affecter la taille du cadre englobant d’un élément doit avoir un AffectsMeasure indicateur défini sur true. Pour plus d’informations, consultez Vue d’ensemble des propriétés de dépendance.

  • Lorsque cela est possible, utilisez un RenderTransform à la place d’un LayoutTransform.

    Il LayoutTransform peut s’agir d’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 élément à la place, car RenderTransform il 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 UpdateLayout méthode force une mise à jour de disposition récursive et n’est fréquemment pas nécessaire. À moins d’être certain qu’une mise à jour complète est nécessaire, laissez le système de disposition appeler cette méthode à votre place.

  • Lors de l’utilisation d’une collection volumineuse Children , envisagez d’utiliser une VirtualizingStackPanel valeur plutôt qu’une collection régulière StackPanel.

    En virtualisant la collection enfant, les VirtualizingStackPanel seuls objets conservés en mémoire qui se trouvent actuellement dans viewPort du parent. De ce fait, 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 est automatiquement mis à l’échelle avec les points par pouce (ppp) du système. Cela fournit aux applications WPF une mise à l’échelle appropriée pour différents paramètres ppp et rend l’application automatiquement consciente.

Toutefois, cette indépendance ppp peut créer un rendu de bord irrégulier en raison de l’anticrénelage. Ces artefacts, qui se présentent généralement sous la forme de bords flous ou semi-transparents, peuvent apparaître quand l’emplacement d’un bord se trouve au milieu d’un pixel d’appareil et non 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 UseLayoutRounding propriété true sur n’importe quel FrameworkElement. S’agissant d’une propriété de dépendance, la valeur se propage à tous les enfants de l’arborescence d’éléments visuels. Pour activer l’arrondi de disposition pour l’ensemble de l’interface utilisateur, définissez-le UseLayoutRoundingtrue sur le conteneur racine. Pour obtenir un exemple, consultez UseLayoutRounding.

Quelle est la prochaine étape ?

Pour bien comprendre en quoi consiste la disposition, il convient dans un premier temps de comprendre comment les éléments sont mesurés et organisés. Pour plus d’informations sur les éléments disponibles Panel , 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 à le mettre ensemble dans une application légère, consultez La procédure pas à pas : Ma première application de bureau WPF.

Voir aussi