Vue d’ensemble des panneaux personnalisés XAMLXAML custom panels overview

Un panneau est un objet qui fournit un comportement de disposition pour les éléments enfants qu’il contient, lorsque le système de disposition XAML (Extensible Application Markup Language) est exécuté et que l’interface utilisateur de votre application est affichée.A panel is an object that provides a layout behavior for child elements it contains, when the Extensible Application Markup Language (XAML) layout system runs and your app UI is rendered.

API importantes  : Panel, ArrangeOverride, MeasureOverrideImportant APIs : Panel, ArrangeOverride, MeasureOverride

Vous pouvez définir des panneaux personnalisés pour la disposition XAML en dérivant une classe personnalisée à partir de la classe Panel.You can define custom panels for XAML layout by deriving a custom class from the Panel class. Vous fournissez le comportement pour votre panneau en substituant les méthodes MeasureOverride et ArrangeOverride et en fournissant la logique qui mesure et organise les éléments enfants.You provide behavior for your panel by overriding the MeasureOverride and ArrangeOverride, supplying logic that measures and arranges the child elements.

Classe de base PanelThe Panel base class

Pour définir une classe de panneau personnalisé, vous pouvez soit dériver directement de la classe Panel, soit dériver de l’une des classes de panneaux pratiques qui ne sont pas sealed, telles que Grid ou StackPanel.To define a custom panel class, you can either derive from the Panel class directly, or derive from one of the practical panel classes that aren't sealed, such as Grid or StackPanel. Il est plus facile de dériver de Panel , car il peut être difficile d’exploiter la logique de disposition existante d’un panneau qui possède déjà un comportement de disposition.It's easier to derive from Panel , because it can be difficult to work around the existing layout logic of a panel that already has layout behavior. De plus, un panneau avec un comportement peut avoir des propriétés existantes qui ne sont pas pertinentes pour les fonctionnalités de disposition de votre panneau.Also, a panel with behavior might have existing properties that aren't relevant for your panel's layout features.

À partir de Panel, votre panneau personnalisé hérite des API suivantes :From Panel, your custom panel inherits these APIs:

  • la propriété Children ;The Children property.
  • les propriétés Background, ChildrenTransitions et IsItemsHost, ainsi que les identificateurs de propriétés de dépendances.The Background, ChildrenTransitions and IsItemsHost properties, and the dependency property identifiers. Aucune de ces propriétés n’est virtuelle. Il n’est donc généralement pas nécessaire de les substituer ou de les remplacer.None of these properties are virtual, so you don't typically override or replace them. Elles ne sont la plupart du temps pas utiles pour les scénarios de panneau personnalisé, même pour la lecture de valeurs ;You don't typically need these properties for custom panel scenarios, not even for reading values.
  • Les méthodes de substitution de disposition MeasureOverride et ArrangeOverride.The layout override methods MeasureOverride and ArrangeOverride. Elles ont été définies à l’origine par FrameworkElement.These were originally defined by FrameworkElement. La classe Panel de base ne les substitue pas, mais des panneaux pratiques comme Grid ont des implémentations de substitution qui sont implémentées comme code natif et sont exécutées par le système.The base Panel class doesn't override these, but practical panels like Grid do have override implementations that are implemented as native code and are run by the system. La fourniture d’implémentations nouvelles (ou additionnelles) pour ArrangeOverride et MeasureOverride constitue la plus grande partie de l’effort nécessaire pour définir un panneau personnalisé.Providing new (or additive) implementations for ArrangeOverride and MeasureOverride is the bulk of the effort you need to define a custom panel.
  • Toutes les autres API de FrameworkElement, UIElement et DependencyObject, telles que Height, Visibility et ainsi de suite.All the other APIs of FrameworkElement, UIElement and DependencyObject, such as Height, Visibility and so on. Vous pouvez parfois faire référence aux valeurs de ces propriétés dans vos substitutions de disposition, mais comme elles ne sont pas virtuelles, vous ne les substituez ou remplacez pas en règle générale.You sometimes reference values of these properties in your layout overrides, but they aren't virtual so you don't typically override or replace them.

L’objet ici est de décrire les concepts de disposition XAML pour que vous puissiez envisager toutes les possibilités de comportement d’un panneau personnalisé dans une disposition.This focus here is to describe XAML layout concepts, so you can consider all the possibilities for how a custom panel can and should behave in layout. Si vous préférez vous plonger tout de suite dans le cœur du sujet et examiner un exemple d’implémentation de panneau personnalisé, consultez l’article BoxPanel, exemple de panneau personnalisé.If you'd rather jump right in and see an example custom panel implementation, see BoxPanel, an example custom panel.

Propriété ChildrenThe Children property

La propriété Children est pertinente lorsqu’il s’agit de panneau personnalisé, car toutes les classes dérivées de Panel utilisent la propriété Children comme emplacement de stockage de leurs éléments enfants dans une collection.The Children property is relevant to a custom panel because all classes derived from Panel use the Children property as the place to store their contained child elements in a collection. Children est désignée comme propriété de contenu XAML pour la classe Panel et toutes les classes dérivées de Panel peuvent hériter du comportement de la propriété de contenu XAML.Children is designated as the XAML content property for the Panel class, and all classes derived from Panel can inherit the XAML content property behavior. Si une propriété est désignée comme propriété de contenu XAML, cela signifie que le balisage XAML peut omettre un élément de propriété lors de la spécification de cette propriété dans le balisage et que les valeurs sont définies comme enfants de balisage immédiat (le « contenu »).If a property is designated the XAML content property, that means that XAML markup can omit a property element when specifying that property in markup, and the values are set as immediate markup children (the "content"). Par exemple, si vous dérivez une classe nommée CustomPanel à partir de Panel qui ne définit aucun nouveau comportement, vous pouvez tout de même utiliser le balisage suivant :For example, if you derive a class named CustomPanel from Panel that defines no new behavior, you can still use this markup:

<local:CustomPanel>
  <Button Name="button1"/>
  <Button Name="button2"/>
</local:CustomPanel>

Quand un analyseur XAML lit ce balisage, il sait que Children est la propriété de contenu XAML pour tous les types dérivés Panel. Il ajoute donc les deux éléments Button à la valeur UIElementCollection de la propriété Children.When a XAML parser reads this markup, Children is known to be the XAML content property for all Panel derived types, so the parser will add the two Button elements to the UIElementCollection value of the Children property. La propriété de contenu XAML facilite une relation parent-enfant rationalisée dans le balisage XAML pour une définition d’interface utilisateur.The XAML content property facilitates a streamlined parent-child relationship in the XAML markup for a UI definition. Pour plus d’informations sur les propriétés de contenu XAML et sur la manière dont les propriétés de collection sont renseignées lors de l’analyse du code XAML, voir le Guide sur la syntaxe XAML.For more info about XAML content properties, and how collection properties are populated when XAML is parsed, see the XAML syntax guide.

Le type de collection qui met à jour la valeur de la propriété Children est la classe UIElementCollection.The collection type that's maintaining the value of the Children property is the UIElementCollection class. UIElementCollection est une collection fortement typée qui utilise UIElement comme type d’élément appliqué.UIElementCollection is a strongly typed collection that uses UIElement as its enforced item type. UIElement étant un type de base hérité par des centaines de types d’éléments d’interface utilisateur pratiques, l’application du type est ici délibérément libre.UIElement is a base type that's inherited by hundreds of practical UI element types, so the type enforcement here is deliberately loose. Toutefois, vous ne pourriez pas avoir un Brush comme enfant direct d’un Panel, ce qui signifie généralement que seuls les éléments censés être visibles dans l’interface utilisateur et participer à la disposition sont détectés comme éléments enfants dans un Panel.But it does enforce that you couldn't have a Brush as a direct child of a Panel, and it generally means that only elements that are expected to be visible in UI and participate in layout will be found as child elements in a Panel.

En règle générale, un panneau personnalisé accepte n’importe quel élément enfant UIElement par une définition XAML, en utilisant simplement les caractéristiques de la propriété Children telle quelle.Typically, a custom panel accepts any UIElement child element by a XAML definition, by simply using the characteristics of the Children property as-is. Dans un scénario avancé, vous pourriez prendre en charge une vérification supplémentaire du type des éléments enfants quand vous itérez au sein de la collection dans vos substitutions de disposition.As an advanced scenario, you could support further type checking of child elements, when you iterate over the collection in your layout overrides.

En plus de parcourir en boucle la collection Children dans les substitutions, votre logique de panneau peut aussi être influencée par Children.Count.Besides looping through the Children collection in the overrides, your panel logic might also be influenced by Children.Count. Vous pourriez avoir une logique qui alloue de l’espace en se basant au moins en partie sur le nombre d’éléments plutôt que sur les tailles souhaitées et les autres caractéristiques des différents éléments.You might have logic that is allocating space at least partly based on the number of items, rather than desired sizes and the other characteristics of individual items.

Substitution des méthodes de dispositionOverriding the layout methods

Le modèle de base pour les méthodes de substitution de disposition ( MeasureOverride et ArrangeOverride) est qu’elles doivent itérer au sein de tous les enfants et appeler la méthode de disposition spécifique à chaque élément enfant.The basic model for the layout override methods ( MeasureOverride and ArrangeOverride) is that they should iterate through all the children and call each child element's specific layout method. Le premier cycle de disposition commence quand le système de disposition XAML définit les éléments visuels pour la fenêtre racine.The first layout cycle starts when the XAML layout system sets the visual for the root window. Comme chaque parent appelle la disposition sur ses enfants, un appel aux méthodes de disposition est propagé à tous les éléments d’interface utilisateur possibles supposés faire partie d’une disposition.Because each parent invokes layout on its children, this propagates a call to layout methods to every possible UI element that is supposed to be part of a layout. La disposition XAML comporte deux phases : la mesure, puis l’organisation.In XAML layout, there are two stages: measure, then arrange.

Vous n’obtenez aucun comportement de méthode de disposition intégré pour MeasureOverride et ArrangeOverride à partir de la classe Panel de base.You don't get any built-in layout method behavior for MeasureOverride and ArrangeOverride from the base Panel class. Les éléments Children ne sont pas affichés automatiquement dans le cadre de l’arborescence d’éléments visuels XAML.Items in Children won't automatically render as part of the XAML visual tree. Vous devez faire en sorte que les éléments soient connus du processus de disposition en appelant des méthodes de disposition sur chacun des éléments que vous trouvez dans Children par l’intermédiaire d’une passe de disposition dans vos implémentations MeasureOverride et ArrangeOverride.It is up to you to make the items known to the layout process, by invoking layout methods on each of the items you find in Children through a layout pass within your MeasureOverride and ArrangeOverride implementations.

Il n’y a aucune raison d’appeler des implémentations de base dans des substitutions de disposition, sauf si vous disposez de votre propre héritage.There's no reason to call base implementations in layout overrides unless you have your own inheritance. Les méthodes natives pour le comportement de disposition (si elles existent) sont exécutées dans tous les cas et le fait de ne pas appeler l’implémentation de base à partir des substitutions n’empêchera pas le comportement natif de se produire.The native methods for layout behavior (if they exist) run regardless, and not calling base implementation from overrides won't prevent the native behavior from happening.

Durant la passe de mesure, votre logique de disposition interroge chaque élément enfant pour connaître la taille souhaitée, en appelant la méthode Measure sur chacun d’eux.During the measure pass, your layout logic queries each child element for its desired size, by calling the Measure method on that child element. L’appel de la méthode Measure établit la valeur de la propriété DesiredSize.Calling the Measure method establishes the value for the DesiredSize property. La valeur de retour de MeasureOverride est la taille souhaitée du panneau proprement dit.The MeasureOverride return value is the desired size for the panel itself.

Durant la passe d’organisation, les positions et tailles des éléments enfants sont déterminées dans l’espace x-y et la composition de la disposition est préparée en vue de l’affichage.During the arrange pass, the positions and sizes of child elements are determined in x-y space and the layout composition is prepared for rendering. Votre code doit appeler Arrange sur chaque élément enfant dans Children pour que le système de disposition détecte que l’élément appartient à la disposition.Your code must call Arrange on each child element in Children so that the layout system detects that the element belongs in the layout. L’appel à Arrange est un précurseur de la composition et du rendu. Il informe le système de disposition de l’emplacement cible de l’élément, lorsque la composition est soumise en vue de l’affichage.The Arrange call is a precursor to composition and rendering; it informs the layout system where that element goes, when the composition is submitted for rendering.

De nombreuses propriétés et valeurs contribuent au fonctionnement de la logique de disposition au moment de l’exécution.Many properties and values contribute to how the layout logic will work at runtime. L’une des manières d’envisager le processus de disposition est de se dire que les éléments sans enfants (généralement ceux qui sont imbriqués le plus profondément dans l’interface utilisateur) sont ceux qui peuvent finaliser les mesures en premier.A way to think about the layout process is that the elements with no children (generally the most deeply nested element in the UI) are the ones that can finalize measurements first. Ils n’ont pas de dépendance envers des éléments enfants qui influencent leur taille souhaitée.They don't have any dependencies on child elements that influence their desired size. Ils peuvent avoir leurs propres tailles souhaitées, qui sont des suggestions de taille jusqu’à ce que la disposition ait réellement lieu.They might have their own desired sizes, and these are size suggestions until the layout actually takes place. Ensuite, la passe de mesure continue à remonter l’arborescence d’éléments visuels jusqu’à ce que l’élément racine ait sa mesure et que toutes les mesures puissent être finalisées.Then, the measure pass continues walking up the visual tree until the root element has its measurements and all the measurements can be finalized.

La disposition candidate doit être ajustée à la fenêtre d’application active, sinon certaines parties de l’interface utilisateur seront coupées.The candidate layout must fit within the current app window or else parts of the UI will be clipped. La logique de coupe est souvent déterminée au niveau des panneaux.Panels often are the place where the clipping logic is determined. La logique de panneau peut souvent déterminer la taille qui est disponible à partir de l’implémentation de MeasureOverride et peut devoir pousser les restrictions de taille vers les enfants et diviser l’espace parmi les enfants pour que tous les éléments soient ajustés du mieux possible.Panel logic can determine what size is available from within the MeasureOverride implementation, and may have to push the size restrictions onto the children and divide space amongst children so that everything fits as best it can. Le résultat de la disposition est, dans l’idéal, quelque chose qui utilise différentes propriétés de toutes les parties de la disposition tout en étant ajusté à la fenêtre de l’application.The result of layout is ideally something that uses various properties of all parts of the layout but still fits within the app window. Cela nécessite à la fois une bonne implémentation de la logique de disposition des panneaux et une conception judicieuse de l’interface utilisateur de la part du code d’application qui génère une interface utilisateur à l’aide de ce panneau.That requires both a good implementation for layout logic of the panels, and also a judicious UI design on the part of any app code that builds a UI using that panel. Votre conception de panneau ne pourra pas être attrayante si la conception globale de l’interface utilisateur comporte plus d’éléments enfants que l’application ne peut en contenir.No panel design is going to look good if the overall UI design includes more child elements than can possibly fit in the app.

Le bon fonctionnement du système de disposition est dû en grande partie au fait que tout élément basé sur FrameworkElement possède déjà une partie de son propre comportement inhérent quand il joue le rôle d’enfant dans un conteneur.A large part of what makes the layout system work is that any element that's based on FrameworkElement already has some of its own inherent behavior when acting as a child in a container. Par exemple, il y a plusieurs API de FrameworkElement qui informent le comportement de disposition ou qui sont nécessaires au fonctionnement de la disposition.For example, there are several APIs of FrameworkElement that either inform layout behavior or are needed to make layout work at all. Ces paramètres sont les suivants :These include:

MeasureOverrideMeasureOverride

La méthode MeasureOverride a une valeur de retour qui est utilisée par le système de disposition comme DesiredSize de départ pour le panneau proprement dit, quand la méthode Measure est appelée sur le panneau par son parent dans la disposition.The MeasureOverride method has a return value that's used by the layout system as the starting DesiredSize for the panel itself, when the Measure method is called on the panel by its parent in layout. Les choix de logique dans la méthode sont tout aussi importants que les valeurs de retour et la logique influence souvent la valeur retournée.The logic choices within the method are just as important as what it returns, and the logic often influences what value is returned.

Toutes les implémentations de MeasureOverride doivent parcourir Children en boucle et appeler la méthode Measure sur chaque élément enfant.All MeasureOverride implementations should loop through Children, and call the Measure method on each child element. L’appel de la méthode Measure établit la valeur de la propriété DesiredSize.Calling the Measure method establishes the value for the DesiredSize property. Cela peut indiquer la quantité d’espace dont a besoin le panneau, ainsi que la manière dont cet espace est réparti parmi les éléments ou dimensionné pour un élément enfant spécifique.This might inform how much space the panel itself needs, as well as how that space is divided among elements or sized for a particular child element.

Voici un squelette très rudimentaire de méthode MeasureOverride :Here's a very basic skeleton of a MeasureOverride method:

protected override Size MeasureOverride(Size availableSize)
{
    Size returnSize; //TODO might return availableSize, might do something else
     
    //loop through each Child, call Measure on each
    foreach (UIElement child in Children)
    {
        child.Measure(new Size()); // TODO determine how much space the panel allots for this child, that's what you pass to Measure
        Size childDesiredSize = child.DesiredSize; //TODO determine how the returned Size is influenced by each child's DesiredSize
        //TODO, logic if passed-in Size and net DesiredSize are different, does that matter?
    }
    return returnSize;
}

Les éléments ont souvent une taille naturelle au moment où ils sont prêts pour la disposition.Elements often have a natural size by the time they're ready for layout. Après la passe de mesure, la propriété DesiredSize peut indiquer cette taille naturelle, si la valeur availableSize que vous avez passée pour Measure était plus petite.After the measure pass, the DesiredSize might indicate that natural size, if the availableSize you passed for Measure was smaller. Si la taille naturelle est plus grande que la valeur availableSize que vous avez passée pour Measure , la propriété DesiredSize est limitée à availableSize.If the natural size is larger than availableSize you passed for Measure , the DesiredSize is constrained to availableSize. Tel est le comportement de l’implémentation interne de Measure , et vos substitutions de disposition doivent prendre ce comportement en compte.That's how Measure 's internal implementation behaves, and your layout overrides should take that behavior into account.

Certains éléments n’ont pas de taille naturelle, car ils ont des valeurs Auto pour Height et Width.Some elements don't have a natural size because they have Auto values for Height and Width. Ces éléments utiliseront la valeur availableSize entière, car c’est ce que représente une valeur Auto : dimensionner l’élément à la taille maximale disponible, que le parent de disposition immédiat communique en appelant Measure avec availableSize.These elements use the full availableSize , because that's what an Auto value represents: size the element to the maximum available size, which the immediate layout parent communicates by calling Measure with availableSize. En pratique, une interface utilisateur est toujours dimensionnée selon une certaine mesure (même s'il s’agit de la fenêtre de niveau supérieur). La passe de mesure finit par résoudre toutes les valeurs Auto aux contraintes parentes, et tous les éléments à valeur Auto obtiennent des mesures réelles (que vous pouvez obtenir en vérifiant ActualWidth et ActualHeight une fois la disposition terminée).In practice, there's always some measurement that a UI is sized to (even if that's the top level window.) Eventually, the measure pass resolves all the Auto values to parent constraints and all Auto value elements get real measurements (which you can get by checking ActualWidth and ActualHeight, after layout completes).

Vous pouvez passer une taille à Measure qui a au moins une dimension infinie pour indiquer que le panneau peut essayer de se dimensionner lui-même en fonction du contenu.It's legal to pass a size to Measure that has at least one infinite dimension, to indicate that the panel can attempt to size itself to fit measurements of its content. Chaque élément enfant mesuré définit sa valeur DesiredSize en fonction de sa taille naturelle.Each child element being measured sets its DesiredSize value using its natural size. Ensuite, durant la passe d’organisation, le panneau est généralement organisé avec cette taille.Then, during the arrange pass, the panel typically arranges using that size.

Les éléments de texte tels que TextBlock ont des valeurs ActualWidth et ActualHeight calculées en fonction de leur chaîne de texte et propriétés de texte même si aucune valeur Height ou Width n’est définie, et ces dimensions doivent être respectées par la logique de votre panneau.Text elements such as TextBlock have a calculated ActualWidth and ActualHeight based on their text string and text properties even if no Height or Width value is set, and these dimensions should be respected by your panel logic. Un texte tronqué est une expérience d’interface utilisateur particulièrement désagréable.Clipping text is a particularly bad UI experience.

Même si votre implémentation n’utilise pas les mesures de taille souhaitée, il est préférable d’appeler la méthode Measure sur chaque élément enfant car certains comportements natifs et internes sont déclenchés par l’appel de Measure.Even if your implementation doesn't use the desired size measurements, it's best to call the Measure method on each child element, because there are internal and native behaviors that are triggered by Measure being called. Pour qu’un élément participe à la disposition, la méthode Measure doit être appelée sur chaque élément enfant durant la passe de mesure et la méthode Arrange doit être appelée durant la passe d’organisation.For an element to participate in layout, each child element must have Measure called on it during the measure pass and the Arrange method called on it during the arrange pass. L’appel de ces méthodes définit des indicateurs internes sur l’objet et renseigne des valeurs (telles que la propriété DesiredSize) dont la logique de disposition du système a besoin quand elle génère l’arborescence d’éléments visuels et affiche l’interface utilisateur.Calling these methods sets internal flags on the object and populates values (such as the DesiredSize property) that the system's layout logic needs when it builds the visual tree and renders the UI.

La valeur de retour de MeasureOverride est basée sur l’interprétation de la propriété DesiredSize par la logique du panneau ou par d’autres considérations de taille pour chacun des éléments enfants dans Children lorsque la méthode Measure est appelée sur eux.The MeasureOverride return value is based on the panel's logic interpreting the DesiredSize or other size considerations for each of the child elements in Children when Measure is called on them. C’est l’interprétation de votre logique qui détermine ce qu’il faut faire avec les valeurs DesiredSize des enfants et comment la valeur de retour de MeasureOverride doit les utiliser.What to do with DesiredSize values from children and how the MeasureOverride return value should use them is up to your own logic's interpretation. En règle générale, vous ne devez pas additionner les valeurs sans modification, car l’entrée de MeasureOverride est souvent une taille disponible fixe suggérée par le parent du panneau.You don't typically add up the values without modification, because the input of MeasureOverride is often a fixed available size that's being suggested by the panel's parent. Si vous dépassez cette taille, le panneau lui-même risque d’être coupé.If you exceed that size, the panel itself might get clipped. Il faut généralement comparer la taille totale des enfants à la taille disponible du panneau et effectuer des ajustements si nécessaire.You'd typically compare the total size of children to the panel's available size and make adjustments if necessary.

Conseils et recommandationsTips and guidance

  • Dans l’idéal, un panneau personnalisé doit convenir en tant que vrai premier élément visuel dans une composition d’interface utilisateur, par exemple à un niveau juste sous Page, UserControl ou un autre élément qui est la racine de la page XAML.Ideally, a custom panel should be suitable for being the first true visual in a UI composition, perhaps at a level immediately under Page, UserControl or another element that is the XAML page root. Dans les implémentations de MeasureOverride, vous ne devez pas retourner systématiquement la valeur Size d’entrée sans examiner les valeurs.In MeasureOverride implementations, don't routinely return the input Size without examining the values. Si la valeur Size de retour contient une valeur Infinity , des exceptions risquent de se produire dans la logique de disposition au moment de l’exécution.If the return Size has an Infinity value in it, this can throw exceptions in runtime layout logic. Une valeur Infinity peut provenir de la fenêtre d’application principale, qui peut défiler et n’a donc pas de hauteur maximale.An Infinity value can come from the main app window, which is scrollable and therefore doesn't have a maximum height. D’autres contenus avec défilement peuvent présenter le même comportement.Other scrollable content might have the same behavior.
  • Une autre erreur courante dans les implémentations de MeasureOverride consiste à retourner une nouvelle valeur Size par défaut (les valeurs de hauteur et de largeur sont égales à 0).Another common mistake in MeasureOverride implementations is to return a new default Size (values for height and width are 0). Vous pouvez commencer par cette valeur, et il peut même s’agir de la valeur correcte si votre panneau détermine qu’aucun des enfants ne doit être affiché.You might start with that value, and it might even be the correct value if your panel determines that none of the children should be rendered. Mais avec une valeur Size par défaut, votre panneau n’est pas dimensionné correctement par son hôte.But, a default Size results in your panel not being sized correctly by its host. Il ne demande pas d’espace dans l’interface utilisateur, n’en obtient donc pas et n’est pas affiché.It requests no space in the UI, and therefore gets no space and doesn't render. Tout le code de votre panneau fonctionne correctement, mais vous ne voyez pas votre panneau ou son contenu, car il est composé avec une hauteur et une largeur égales à 0.All your panel code otherwise might be functioning fine, but you still won't see your panel or contents thereof if it's being composed with zero height, zero width.
  • Dans les substitutions, résistez à la tentation d’effectuer une conversion de type (transtypage) des éléments enfants vers FrameworkElement et d’utiliser des propriétés qui sont calculées suite à la disposition, en particulier ActualWidth et ActualHeight.Within the overrides, avoid the temptation to cast child elements to FrameworkElement and use properties that are calculated as a result of layout, particularly ActualWidth and ActualHeight. Pour la plupart des scénarios courants, vous pouvez baser la logique sur la valeur DesiredSize de l’enfant, et vous n’avez pas besoin des propriétés en rapport avec Height ou Width d’un élément enfant.For most common scenarios, you can base the logic on the child's DesiredSize value and you won't need any of the Height or Width related properties of a child element. Pour les cas particuliers où vous connaissez le type d’élément et où vous possédez des informations supplémentaires, par exemple la taille naturelle d’un fichier image, vous pouvez utiliser ces informations spécifiques, car il ne s’agit pas d’une valeur modifiée de manière active par les systèmes de disposition.For specialized cases, where you know the type of element and have additional information, for example the natural size of an image file, you can use your element's specialized information because it's not a value that is actively being altered by layout systems. Le fait d’inclure des propriétés calculées par la disposition dans le cadre de la logique de disposition augmente de manière significative le risque de définir une boucle de disposition involontaire.Including layout-calculated properties as part of layout logic substantially increases the risk of defining an unintentional layout loop. Ces boucles provoquent une condition dans laquelle une disposition valide ne peut pas être créée et le système peut lever une exception LayoutCycleException si la boucle est irrécupérable.These loops cause a condition where a valid layout can't be created and the system can throw a LayoutCycleException if the loop is not recoverable.
  • Les panneaux répartissent en général leur espace disponible entre plusieurs éléments enfants, bien que la façon exacte dont l’espace est réparti varie.Panels typically divide their available space between multiple child elements, although exactly how space is divided varies. Par exemple, Grid implémente une logique de disposition qui utilise ses valeurs RowDefinition et ColumnDefinition pour diviser l’espace dans les cellules Grid , avec prise en charge à la fois des valeurs de pixels et de redimensionnement proportionnel.For example, Grid implements layout logic that uses its RowDefinition and ColumnDefinition values to divide the space into the Grid cells, supporting both star-sizing and pixel values. S’il s’agit de valeurs de pixels, la taille disponible pour chaque enfant est déjà connue. Elle est donc passée comme taille d’entrée pour une méthode Measure de style grille.If they're pixel values, the size available for each child is already known, so that's what is passed as input size for a grid-style Measure.
  • Les panneaux eux-mêmes peuvent introduire un espace réservé pour l’espacement entre les éléments.Panels themselves can introduce reserved space for padding between items. Dans ce cas, veillez à exposer les mesures en tant que propriété distincte de Margin ou de toute propriété Padding.If you do this, make sure to expose the measurements as a property that's distinct from Margin or any Padding property.
  • Des éléments peuvent avoir des valeurs pour leurs propriétés ActualWidth et ActualHeight basées sur une passe de disposition précédente.Elements might have values for their ActualWidth and ActualHeight properties based on a previous layout pass. Si des valeurs changent, le code d’interface utilisateur de l’application peut placer des gestionnaires pour LayoutUpdated sur des éléments s’il y a une logique spéciale à exécuter, mais la logique de panneau n’a en général pas besoin de vérifier s’il y a des modifications avec la gestion des événements.If values change, app UI code can put handlers for LayoutUpdated on elements if there's special logic to run, but panel logic typically doesn't need to check for changes with event handling. Le système de disposition détermine déjà quand réexécuter la disposition car une propriété en rapport avec la disposition a changé de valeur et les méthodes MeasureOverride et ArrangeOverride d’un panneau sont appelées automatiquement dans les circonstances appropriées.The layout system is already making the determinations of when to re-run layout because a layout-relevant property changed value, and a panel's MeasureOverride or ArrangeOverride are called automatically in the appropriate circumstances.

ArrangeOverrideArrangeOverride

La méthode ArrangeOverride a une valeur de retour Size qui est utilisée par le système de disposition lors de l’affichage du panneau proprement dit, quand la méthode Arrange est appelée sur le panneau par son parent dans la disposition.The ArrangeOverride method has a Size return value that's used by the layout system when rendering the panel itself, when the Arrange method is called on the panel by its parent in layout. Il est courant que la valeur finalSize d’entrée et la valeur Size retournée par ArrangeOverride soient identiques.It's typical that the input finalSize and the ArrangeOverride returned Size are the same. Si ce n’est pas le cas, cela veut dire que le panneau essaie de s’allouer une taille différente de celle déclarée comme disponible par les autres participants à la disposition.If they aren't, that means the panel is attempting to make itself a different size than what the other participants in layout claim is available. La taille finale est basée sur l’exécution précédente de la passe de mesure de disposition dans le code de panneau. C’est pourquoi le fait de retourner une taille différente n’est pas anodin : cela signifie que vous ignorez délibérément la logique de mesure.The final size was based on having previously run the measure pass of layout through your panel code, so that's why returning a different size isn't typical: it means you are deliberately ignoring measure logic.

Ne retournez pas une valeur Size avec un composant Infinity.Don't return a Size with an Infinity component. L’utilisation d’une telle valeur Size lève une exception depuis la disposition interne.Trying to use such a Size throws an exception from internal layout.

Toutes les implémentations de ArrangeOverride doivent parcourir Children en boucle et appeler la méthode Arrange sur chaque élément enfant.All ArrangeOverride implementations should loop through Children, and call the Arrange method on each child element. Comme Measure, Arrange n’a pas de valeur de retour.Like Measure, Arrange doesn't have a return value. Contrairement à Measure , aucune propriété calculée n’est définie en tant que résultat (toutefois, l’élément en question déclenche généralement un événement LayoutUpdated).Unlike Measure , no calculated property gets set as a result (however, the element in question typically fires a LayoutUpdated event).

Voici un squelette très rudimentaire de méthode ArrangeOverride :Here's a very basic skeleton of an ArrangeOverride method:

protected override Size ArrangeOverride(Size finalSize)
{
    //loop through each Child, call Arrange on each
    foreach (UIElement child in Children)
    {
        Point anchorPoint = new Point(); //TODO more logic for topleft corner placement in your panel
       // for this child, and based on finalSize or other internal state of your panel
        child.Arrange(new Rect(anchorPoint, child.DesiredSize)); //OR, set a different Size 
    }
    return finalSize; //OR, return a different Size, but that's rare
}

La passe d’organisation de disposition peut avoir lieu sans être précédée d’une passe de mesure.The arrange pass of layout might happen without being preceded by a measure pass. Cependant, cela ne se produit que lorsque le système de disposition a déterminé qu’aucune propriété n’ayant changé n’affecterait les mesures précédentes.However, this only happens when the layout system has determined no properties have changed that would have affected the previous measurements. Par exemple, si un alignement change, il est inutile de mesurer à nouveau cet élément spécifique car sa propriété DesiredSize ne changerait pas en cas de modification de son choix d’alignement.For example, if an alignment changes, there's no need to re-measure that particular element because its DesiredSize would not change when its alignment choice changes. En revanche, si ActualHeight change sur un élément quelconque dans la disposition, une nouvelle passe de mesure est nécessaire.On the other hand, if ActualHeight changes on any element in a layout, a new measure pass is needed. Le système de disposition détecte automatiquement les vrais changements de mesure et rappelle la passe de mesure, puis il exécute la passe d’organisation.The layout system automatically detects true measure changes and invokes the measure pass again, and then runs another arrange pass.

L’entrée de Arrange accepte une valeur Rect.The input for Arrange takes a Rect value. Le moyen le plus répandu pour construire ce Rect consiste à utiliser le constructeur qui a une entrée Point et une entrée Size.The most common way to construct this Rect is to use the constructor that has a Point input and a Size input. Point est le point où l’angle supérieur gauche du cadre englobant pour l’élément doit être placé.The Point is the point where the top left corner of the bounding box for the element should be placed. Size correspond aux dimensions utilisées pour afficher cet élément spécifique.The Size is the dimensions used to render that particular element. On utilise souvent la propriété DesiredSize de cet élément comme cette valeur Size , car l’établissement de la propriété DesiredSize pour tous les éléments impliqués dans la disposition était l’objectif de la passe de mesure de disposition.You often use the DesiredSize for that element as this Size value, because establishing the DesiredSize for all elements involved in layout was the purpose of the measure pass of layout. (La passe de mesure détermine le dimensionnement des éléments de manière itérative pour que le système de disposition puisse optimiser le placement des éléments une fois qu’il atteint la passe d’organisation.)(The measure pass determines all-up sizing of the elements in an iterative way so that the layout system can optimize how elements are placed once it gets to the arrange pass.)

Ce qui varie en général entre les implémentations de ArrangeOverride, c’est la logique par laquelle le panneau détermine le composant Point pour l’organisation de chaque enfant.What typically varies between ArrangeOverride implementations is the logic by which the panel determines the Point component of how it arranges each child. Un panneau de positionnement absolu tel que Canvasutilise les informations de placement explicites qu’il obtient à partir de chaque élément par l’intermédiaire des valeurs Canvas.Left et Canvas.Top.An absolute positioning panel such as Canvas uses the explicit placement info that it gets from each element through Canvas.Left and Canvas.Top values. Un panneau de division de l’espace tel que Grid aurait des opérations mathématiques qui diviseraient l’espace disponible en cellules et chaque cellule aurait une valeur x-y indiquant où son contenu devrait être placé et organisé.A space-dividing panel such as Grid would have mathematical operations that divided the available space into cells and each cell would have an x-y value for where its content should be placed and arranged. Un panneau adaptatif tel que StackPanel pourrait s’étendre pour s’ajuster au contenu dans sa dimension d’orientation.An adaptive panel such as StackPanel might be expanding itself to fit content in its orientation dimension.

Il existe d’autres influences sur le positionnement des éléments dans la disposition, au-delà de ce que vous contrôlez directement et passez à Arrange.There are still additional positioning influences on elements in layout, beyond what you directly control and pass to Arrange. Ces influences proviennent de l’implémentation native interne de Arrange qui est commune à tous les types dérivés FrameworkElement et augmentée par d’autres types tels que les éléments de texte.These come from the internal native implementation of Arrange that's common to all FrameworkElement derived types and augmented by some other types such as text elements. Par exemple, des éléments peuvent avoir une marge et un alignement, tandis que d’autres peuvent avoir un espacement.For example, elements can have margin and alignment, and some can have padding. Ces propriétés interagissent souvent.These properties often interact. Pour plus d’informations, voir Alignement, marge et espacement.For more info, see Alignment, margin, and padding.

Panneaux et contrôlesPanels and controls

Évitez de placer dans un panneau une fonctionnalité qui devrait plutôt être générée en tant que contrôle personnalisé.Avoid putting functionality into a custom panel that should instead be built as a custom control. Le rôle d’un panneau consiste à présenter tout contenu d’élément enfant qui existe à l’intérieur du panneau, en tant que fonction de disposition qui se produit automatiquement.The role of a panel is to present any child element content that exists within it, as a function of layout that happens automatically. Le panneau peut ajouter des décorations au contenu (un peu comme un objet Border ajoute la bordure autour de l’élément qu’il présente) ou effectuer d’autres ajustements liés à la disposition (comme l’espacement).The panel might add decorations to content (similar to how a Border adds the border around the element it presents), or perform other layout-related adjustments like padding. Mais vous ne devez pas aller plus loin lors de l’extension de la sortie de l’arborescence d’éléments visuels au-delà du signalement et de l’utilisation d’informations provenant des enfants.But that's about as far as you should go when extending the visual tree output beyond reporting and using information from the children.

Si une interaction est accessible à l’utilisateur, vous devez écrire un contrôle personnalisé, et non un panneau.If there's any interaction that's accessible to the user, you should write a custom control, not a panel. Par exemple, un panneau ne doit pas ajouter de fenêtres d’affichage de défilement à du contenu qu’il présente, même si l’objectif est d’empêcher la troncature du texte, car les barres de défilement, pouces et autres sont des parties de contrôle interactives.For example, a panel shouldn't add scrolling viewports to content it presents, even if the goal is to prevent clipping, because the scrollbars, thumbs and so on are interactive control parts. (Le contenu peut quand même avoir des barres de défilement, mais vous devez laisser la logique de l’enfant en décider.(Content might have scrollbars after all, but you should leave that up to the child's logic. Ne l'imposez pas en ajoutant le défilement comme opération de disposition.) Vous pouvez très bien créer un contrôle et écrire un panneau personnalisé qui joue un rôle important dans l'arborescence d'éléments visuels de ce contrôle, lorsqu'il s'agit de présenter le contenu dans ce contrôle,Don't force it by adding scrolling as a layout operation.) You might create a control and also write a custom panel that plays an important role in that control's visual tree, when it comes to presenting content in that control. mais le contrôle et le panneau doivent être des objets de code distincts.But the control and the panel should be distinct code objects.

Cette distinction entre un contrôle et un panneau est importante en raison de l’accessibilité et de Microsoft UI Automation.One reason the distinction between control and panel is important is because of Microsoft UI Automation and accessibility. Les panneaux fournissent un comportement de disposition visuelle, et non un comportement logique.Panels provide a visual layout behavior, not a logical behavior. La manière dont un élément d’interface utilisateur apparaît visuellement n’est pas un aspect de l’interface utilisateur qui est en général important dans les scénarios d’accessibilité.How a UI element appears visually is not an aspect of UI that is typically important to accessibility scenarios. L’accessibilité s’intéresse à l’affichage des parties d’une application qui sont importantes pour comprendre une interface utilisateur.Accessibility is about exposing the parts of an app that are logically important to understanding a UI. Lorsqu’une interaction est nécessaire, les contrôles doivent exposer les possibilités d’interaction à l’infrastructure UI Automation.When interaction is required, controls should expose the interaction possibilities to the UI Automation infrastructure. Pour plus d’informations, voir Homologues d’automation personnalisés.For more info, see Custom automation peers.

Autres API de dispositionOther layout API

D’autres API font partie du système de disposition mais ne sont pas déclarées par Panel.There are some other APIs that are part of the layout system, but aren't declared by Panel. Vous pouvez les utiliser dans une implémentation de panneau ou dans un contrôle personnalisé qui utilise des panneaux.You might use these in a panel implementation or in a custom control that uses panels.

  • UpdateLayout, InvalidateMeasure et InvalidateArrange sont des méthodes qui initient une passe de disposition.UpdateLayout, InvalidateMeasure, and InvalidateArrange are methods that initiate a layout pass. InvalidateArrange peut ne pas déclencher de passe de mesure, mais les deux autres en déclenchent une.InvalidateArrange might not trigger a measure pass, but the other two do. N’appelez jamais ces méthodes à partir d’une substitution de méthode de disposition, car elles provoqueront presque à coup sûr une boucle de disposition.Never call these methods from within a layout method override, because they're almost sure to cause a layout loop. Le code de contrôle n’a généralement pas besoin de les appeler non plus.Control code doesn't typically need to call them either. La plupart des aspects de la disposition sont déclenchés automatiquement grâce à la détection des modifications apportées aux propriétés de disposition définies par l’infrastructure, telles que Width et ainsi de suite.Most aspects of layout are triggered automatically by detecting changes to the framework-defined layout properties such as Width and so on.
  • LayoutUpdated est un événement déclenché lorsqu'un aspect de disposition de l'élément a changé.LayoutUpdated is an event that fires when some aspect of layout of the element has changed. Cela n’est pas spécifique aux panneaux ; l’événement est défini par FrameworkElement.This isn't specific to panels; the event is defined by FrameworkElement.
  • SizeChanged qui ne se déclenche qu'une fois que les passes de disposition ont été finalisées. Il indique que ActualHeight ou ActualWidth a changé en conséquence.SizeChanged is an event that fires only after layout passes are finalized, and indicates that ActualHeight or ActualWidth have changed as a result. Il s’agit d’un autre événement FrameworkElement.This is another FrameworkElement event. Dans certains cas, LayoutUpdated se déclenche, mais pas SizeChanged.There are cases where LayoutUpdated fires, but SizeChanged does not. Par exemple, le contenu interne peut être réorganisé, mais la taille de l’élément n’a pas changé.For example the internal contents might be rearranged, but the element's size didn't change.

Informations de référenceReference

ConceptsConcepts