Partager via


Système de disposition

Cette rubrique décrit le système de disposition Windows Presentation Foundation (WPF). Comprendre comment et quand les 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

  • Système de disposition

  • Mesure et réorganisation d'enfants

  • Comportements des éléments de volet et de disposition personnalisée

  • Considérations relatives aux performances de la disposition

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

  • Quoi d'autre ?

Zones englobantes d'élément

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

Voici une illustration.

Grille classique, sans cadre englobant superposé.

Cette disposition peut être accomplie à l'aide du 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. Tandis que le texte remplit uniquement l'angle supérieur gauche de la première colonne, l'espace alloué pour le TextBlock est réellement beaucoup plus grand. Le cadre englobant de tout FrameworkElement peut être extrait à l'aide de la méthode GetLayoutSlot. L'illustration suivante montre le cadre englobant pour l'élément TextBlock.

Le cadre englobant du TextBlock est maintenant visible.

Comme indiqué par le rectangle jaune, l'espace alloué pour l'élément TextBlock est réellement beaucoup plus grand qu'il apparaît. Comme des éléments supplémentaires sont ajoutés au Grid, cette allocation pourrait réduire ou se développer, selon le type et la taille des éléments ajoutés.

L'emplacement de disposition du TextBlock est traduit dans un Path à l'aide de la méthode GetLayoutSlot. Cette technique peut être utile pour l'affichage du cadre englobant d'un élément.

Private Sub getLayoutSlot1(ByVal sender As Object, ByVal e As RoutedEventArgs)
    Dim myRectangleGeometry As New RectangleGeometry
    myRectangleGeometry.Rect = LayoutInformation.GetLayoutSlot(txt1)
    Dim myGeometryDrawing As New GeometryDrawing
    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
private void getLayoutSlot1(object sender, System.Windows.RoutedEventArgs e)
{
    RectangleGeometry myRectangleGeometry = new RectangleGeometry();
    myRectangleGeometry.Rect = LayoutInformation.GetLayoutSlot(txt1);
    GeometryDrawing myGeometryDrawing = new GeometryDrawing();
    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();
}

Système de disposition

Dans sa forme la plus simple, la disposition est un système récursif qui conduit au dimensionnement, au positionnement et au dessin d'un élément. Plus spécifiquement, la disposition décrit le processus de mesure et de réorganisation des membres de la collection Children d'un élément Panel. La disposition est un processus intensif. Plus grande est la collection Children, plus important sera le nombre de calculs qui doivent être faits. Il est également possible de définir une complexité en fonction du comportement de disposition défini par l'élément Panel qui possède la collection. Un Panel relativement simple, tel que Canvas, peut avoir de bien meilleures performances qu'un Panel plus complexe, tel que Grid.

Chaque fois qu'un UIElement enfant modifie sa position, il a la possibilité de déclencher une nouvelle passe via le système de disposition. Il est par conséquent important de comprendre les événements qui peuvent appeler le système de disposition, car un appel inutile risque d'altérer les performances de l'application. Les éléments suivants décrivent le processus qui se produit lorsque le système de disposition est appelé.

  1. Un UIElement enfant commence le processus de disposition par la mesure de ses propriétés principales.

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

  3. La logique spécifique Panel est appliquée, telle que le sens Dock ou l'empilement Orientation.

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

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

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

Ce processus et la manière de l'appeler sont définis de façon plus détaillée dans les sections suivantes.

Mesure et réorganisation d'enfants

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

Pendant la phase 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 à être explicitement appelée pour que la disposition se produise.

En premier lieu, les propriétés de taille natives de UIElement sont évaluées, telles que Clip et Visibility. Cela génère une valeur nommée constraintSize passée à MeasureCore.

Deuxièmement, les propriétés d'infrastructure 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 UIElement sous-jacent, (Height, Width, Margin et Style, par exemple). Chacune de ces propriétés peut modifier l'espace nécessaire à l'affichage de l'élément. Puis MeasureOverride est appelé avec constraintSize comme un paramètre.

RemarqueRemarque

Il existe une différence entre les propriétés de Height et Width et ActualHeight et ActualWidth.Par exemple, la propriété ActualHeight est une valeur calculée en fonction 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, selon une passe de rendu réel, et peut par conséquent rester légèrement en retrait de la valeur définie des propriétés, telle que Height, qui est la base de la modification d'entrée.

Du fait que ActualHeight est une valeur calculée, vous devez savoir que des modifications multiples ou incrémentielles signalées peuvent se produire sur cette valeur résultant de différentes opérations par le système de disposition.Le système de disposition peut calculer l'espace de mesure requis pour les éléments enfants, les contraintes par l'élément parent, et ainsi de suite.

L'objectif ultime de la phase de mesure est pour l'enfant de déterminer sa DesiredSize, qui se produit pendant l'appel de MeasureCore. La valeur DesiredSize est stockée par Measure pour une utilisation pendant la passe de réorganisation du contenu.

La passe de réorganisation du contenu 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 passée à la méthode ArrangeCore pour traitement.

La méthode ArrangeCore évalue la DesiredSize de l'enfant et évalue toutes marges supplémentaires qui peuvent affecter la taille rendue de l'élément. ArrangeCore génère une arrangeSize, qui est passée à la méthode ArrangeOverride du Panel en tant que paramètre. ArrangeOverride génère la 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, par exemple) 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 alors retourné au Panel parent, et le processus de disposition est complet.

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

WPF inclut un groupe d'éléments qui dérivent de Panel. Ces éléments Panel permettent de nombreuses dispositions complexes. Par exemple, l'empilement d'éléments peut être facilement accompli à l'aide de l'élément StackPanel, tandis que les dispositions de flux plus complexes et libres sont possible à l'aide d'un Canvas.

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

Nom du volet

Description

Canvas

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

DockPanel

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

Grid

Définit une grille flexible qui se compose de colonnes et des lignes.

StackPanel

Réorganise des éléments enfants sur une seule ligne pouvant être 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 de gauche à droite des éléments enfants dans une position séquentielle, en arrêtant le contenu à la ligne suivante au bord de la zone conteneur. Le classement continue ensuite séquentiellement de haut en bas ou de droite à gauche, selon la valeur de la propriété Orientation.

Pour les applications qui requièrent une disposition qui ne peut utiliser aucun des éléments Panel prédéfinis, les comportements de disposition personnalisée peuvent être obtenus en héritant de Panel et en substituant les méthodes MeasureOverride et ArrangeOverride. Pour obtenir un exemple, consultez Panneau radial personnalisé, exemple.

Considérations relatives aux performances de la disposition

La disposition est un processus récursif. Chaque élément enfant dans 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é lorsque ce n'est pas nécessaire. Les considérations suivantes peuvent vous aider à accomplir de meilleures performances.

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

    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 valeurs de propriétés qui forceront une mise à jour récursive par le système de disposition. En général, toute propriété qui peut affecter la taille du cadre englobant d'un élément doit avoir un indicateur AffectsMeasure ayant pour valeur true. Pour plus d'informations, consultez Vue d'ensemble des propriétés de dépendance.

  • Lorsque cela est possible, utilisez un RenderTransform au lieu d'un LayoutTransform.

    Une LayoutTransform peut être une méthode très utile pour affecter le contenu d'un user interface (UI). Toutefois, si l'effet de la transformation ne doit pas avoir d'impact sur la position d'autres éléments, il vaut mieux utiliser à la place un RenderTransform, parce que RenderTransform n'appelle pas le système de disposition. LayoutTransform applique sa transformation et force une mise à jour de la disposition récursive dont il faut tenir compte pour la nouvelle position de l'élément affecté.

  • Évitez les appels inutiles à UpdateLayout.

    La méthode UpdateLayout force une mise à jour de la disposition récursive et n'est pas souvent nécessaire. À moins d'être sûr qu'une mise à jour complète est obligatoire, reposez-vous sur le système de disposition pour appeler cette méthode à votre place.

  • Lorsque vous utilisez une grande collection Children, envisagez d'utiliser un VirtualizingStackPanel au lieu d'un StackPanel normal.

    En virtualisant la collection enfant, le VirtualizingStackPanel garde uniquement en mémoire les objets qui sont actuellement dans la fenêtre d'affichage du parent. En conséquence, 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 du périphérique pour garantir l'indépendance vis-à-vis du périphérique et de la résolution. Chaque pixel indépendant du périphérique s'ajuste automatiquement sur le paramètre dots per inch (dpi) du système. Cela fournit aux applications WPF la mise à l'échelle appropriée pour différents paramètres dpi et rend l'application capable de prendre automatiquement en compte le paramètre dpi.

Cependant, cette indépendance dpi peut générer un rendu irrégulier des bords en raison de l'anticrénelage. Ces artefacts, apparaissant généralement avec des bords flous ou semi-transparents, peuvent se produire lorsque l'emplacement d'un bord tombe au milieu d'un pixel de périphérique au lieu d'être entre des pixels de périphériques. Le système de disposition offre un moyen de réglage avec l'arrondi de disposition. L'arrondi de disposition est l'endroit où le système de disposition arrondit des valeurs en pixels non intégrales pendant la passe de disposition.

L'arrondi de disposition est désactivé par défaut. Pour permettre l'arrondi de disposition, affectez à la propriété UseLayoutRounding la valeur true sur tout FrameworkElement. Étant donné qu'il s'agit d'une propriété de dépendance, la valeur sera propagée à tous les enfants dans l'arborescence d'éléments visuels. Pour permettre l'arrondi de disposition pour l'interface utilisateur entière, affectez au conteneur racine UseLayoutRounding la valeur true. Pour obtenir un exemple, consultez UseLayoutRounding.

Quoi d'autre ?

Comprendre comment les éléments sont mesurés et organisés est la première étape dans la connaissance de la disposition. Pour plus d'informations sur les éléments Panel disponibles, consultez Vue d'ensemble de Panel. 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. Pour obtenir un exemple d'un élément Panel personnalisé, consultez Panneau radial personnalisé, exemple Lorsque vous êtes prêt à tout réunir dans une application légère, consultez Procédure pas à pas : mise en route de WPF.

Voir aussi

Référence

FrameworkElement

UIElement

Concepts

Vue d'ensemble de Panel

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

Optimisation des performances : disposition et conception