Système de disposition

Mise à jour : novembre 2007

Cette rubrique décrit le système de disposition Windows Presentation Foundation (WPF). Il est primordial de comprendre comment et quand se produisent les calculs de disposition essentiel pour l'élaboration d'interfaces utilisateur attrayantes hautes performances.

Cette rubrique contient les sections suivantes.

  • Système de disposition

  • Zones englobantes d'élément

  • 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

  • Quoi d'autre ?

  • Rubriques connexes

Système de disposition

Le terme "disposition" décrit le processus de mesure et de réorganisation des membres d'une collection Children d'un élément Panel puis de les dessiner à l'écran. C'est un processus intensif, et plus la collection Children est importante, et plus le nombre de calculs effectués est élevé. 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. Une disposition relativement simple telle que Canvas peut générer d'excellentes performances lorsqu'un Panel plus complexe tel que Grid n'est pas requis.

Chaque fois qu'un enfant UIElement modifie sa position, il a la possibilité de déclencher une nouvelle passe par 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 un appel inutile peut entraîner des performances médiocres de l'application.

Dans sa forme la plus simple, la disposition est un système récursif qui conduit au dimensionnement, positionnement et dessin d'un élément à l'écran. 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 enfant Panel fournit ses propres MeasureOverride et méthodes ArrangeOverride pour accomplir son propre comportement de disposition spécifique. C'est la série d'événements qui se produit à chaque fois que 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, Height et Margin.

  3. La logique spécifique Panel est appliquée, tel 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 les moyens par lesquels il est appelé, sont définis plus en détail dans les sections qui suivent.

Zones englobantes d'élément

Lors de la préparation d'une disposition d'application dans Windows Presentation Foundation (WPF), il est important de comprendre la zone englobante qui entoure tous les éléments. Cette abstraction aide à comprendre le comportement du système de disposition. Chaque FrameworkElement a consommé par le système de disposition peut être pensé comme un rectangle emboîté dans une partition de disposition. Une classe, LayoutInformation, est exposée et peut retourner les limites géométriques de l'allocation de disposition d'un élément, ou emplacement. La taille de ce rectangle est déterminée par le système, en calculant l'espace écran disponible, la taille de toutes les contraintes, les propriétés de disposition spécifiques comme la marge et la marge intérieure, et le comportement individuel de l'élément Panel parent. En traitant ces données, le système est en mesure de calculer la position de tous les enfants d'un Panel donné. Il est important de se souvenir que les caractéristiques de dimensionnement définies sur l'élément parent (tel qu'un Border) affectent ses enfants.

Considérez le scénario de disposition simple suivant comme exemple.

Grille classique, sans cadre englobant superposé.

Cette disposition peut être accomplie à l'aide du XAML (Extensible Application Markup Language) 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>

L'élément TextBlock solitaire est hébergé dans un Grid, et pendant que le texte remplit uniquement le coin supérieur gauche de la colonne dans laquelle il a été placé, l'espace alloué pour le TextBlock est en réalité beaucoup plus grand. La zone englobante de tout FrameworkElement peut être récupérée à l'aide de la méthode GetLayoutSlot. À l'aide de cette méthode, la zone englobante de l'élément TextBlock est superposée (cela est possible car le TextBlock est hébergé dans un Grid, un élément Panel qui autorise le partage des coordonnées de disposition).

Le cadre englobant du TextBlock est maintenant visible.

Comme cela est maintenant apparent par la ligne blanche qui l'entoure, la partition allouée à l'élément TextBlock est en réalité beaucoup plus grande que l'espace qu'elle remplit. 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 retourné et traduit dans un Path à l'aide de la méthode GetLayoutSlot, une technique qui peut être utile pour afficher la zone englobante 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();
}

Mesure et réorganisation d'enfants

Lorsque le contenu d'un objet Window est restitué, le système de disposition est appelé automatiquement. Pour afficher le contenu, le Content de la fenêtre doit définir un Panel racine qui sert pour définir une infrastructure par laquelle les Children sont organisés sur l'écran. Consultez Comportements des éléments de volet et de disposition personnalisée pour une liste d'éléments Panel disponibles et des informations sur la création d'éléments de disposition personnalisée.

La première passe de disposition est la passe de mesure, où 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.

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 appelée constraintSize qui est passée à MeasureCore.

Deuxièmement, les propriétés d'infrastructure définies sur FrameworkElement sont traitées, en affectant la valeur de constraintSize. Ces propriétés ont tendance à décrire les caractéristiques de dimensionnement du UIElement sous-jacent, par exemple Height, Width, Margin et Style. Chacune de ces propriétés peut modifier l'espace nécessaire à l'affichage de l'élément. MeasureOverride est ensuite appelée 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 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 derrière 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 passe de mesure est pour l'enfant de déterminer sa DesiredSize, qui est générée pendant l'appel MeasureCore. Cette valeur est stockée par Measure pour une utilisation pendant le processus de réorganisation du contenu.

Le processus 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 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 et génère une arrangeSize, transmise au ArrangeOverride du volet comme paramètre. ArrangeOverride génère la finalSize de l'enfant, et enfin la méthode ArrangeCore fait une dernière évaluation des propriétés d'offset telles que la marge et l'alignement, et place l'enfant dans son emplacement de disposition. L'enfant n'a pas besoin de (et fréquemment ne veut pas) remplir l'espace alloué entier. 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

Le Windows Presentation Foundation (WPF) inclut une suite dérivée d'éléments Panel qui permettent de nombreuses dispositions complexes. Les scénarios courants, tels que l'empilage d'éléments, peuvent être facilement accomplis en utilisant l'élément StackPanel, alors que des dispositions d'écoulement plus complexes et libres sont possibles à l'aide d'un Canvas.

Le tableau suivant récapitule les éléments de disposition 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 de 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. 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.

Pour les exemples de code qui affichent l'utilisation pour chacun de ces éléments, consultez Exemples de dispositions.

Pour les scénarios qui requièrent une disposition d'application dont il n'est pas possible d'utiliser chacun des éléments Panel prédéfinis, les comportements de disposition personnalisée peuvent être accomplis en héritant de Panel et en substituant les MeasureOverride et méthodes 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é à chaque appel du système. En conséquence, le déclenchement du système doit être évité lorsque ce n'est pas nécessaire. Les conseils suivants peuvent vous aider à obtenir de meilleures performances.

Les propriétés de dépendance dont les valeurs peuvent provoquer l'initialisation du système de disposition sont marquées avec des indicateurs publics. AffectsMeasure et AffectsArrange fournissent des indices utiles comme les modifications de valeur de propriété 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 de la zone englobante d'un élément doit définir l'indicateur AffectsMeasure à la valeur True. Pour plus d'informations, consultez Vue d'ensemble des propriétés de dépendance.

Une LayoutTransform peut être une méthode très utile pour affecter le contenu d'un interface utilisateur (UI). Toutefois, si l'effet de la transformation n'a pas besoin d'affecter la position d'autres éléments, il est préférable d'utiliser 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 prendre en compte la nouvelle position de l'élément affecté.

Évitez les appels inutiles à UpdateLayout. Cette méthode force une mise à jour de disposition récursive et n'est pas souvent nécessaire. À moins que vous ne soyez certain qu'une mise à jour complète est requise, laissez le système de disposition appeler cette méthode à votre place.

Lorsque vous traitez avec une grande collection Children, envisagez d'utiliser le VirtualizingStackPanel plutôt qu'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.

Quoi d'autre ?

Comprendre comment les éléments sont mesurés et réorganisés est la première étape permettant de comprendre la disposition comme un système. Pour une compréhension plus approfondie des é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 Volet personnalisé, consultez Panneau radial personnalisé, exemple. Lorsque vous êtes prêt à réunir tout dans une application légère, consultez Mise en route de Windows Presentation Foundation.

Voir aussi

Concepts

Vue d'ensemble de Panel

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

Alignement des pixels dans les applications WPF

XAMLPad

Optimisation des performances : disposition et conception

Référence

FrameworkElement

UIElement