38 votes

Qu'est-ce que Panel.IsItemsHost fait exactement?

À quoi sert la propriété attachée Panel.IstItemsHost ?

Je vois de nombreux exemples de personnes la définissant dans le modèle ItemsContainer pour un ItemsControl, mais la non-documentation sur MSDN n'explique pas pourquoi ou quels avantages confère le réglage de la propriété.

38voto

Will Points 76760

Dire que j'ai un contrôle ItemsControl. Je veux utiliser un panneau personnalisé qui fait défiler les éléments lorsque vous faites défiler; il s'appelle SwoopPanel. Maintenant, comment dire à l'ItemsControl d'utiliser mon SwoopPanel pour contenir les modèles qu'il crée?

La méthode rapide consiste à définir le ItemsPanel sur l'ItemsControl:

Cependant, parfois cela ne fonctionne pas pour vous. Peut-être souhaitez-vous personnaliser la façon dont le SwoopPanel est présenté dans l'interface utilisateur, et le seul moyen de contourner cela est de modifier le modèle de contrôle de l'ItemsControl. Maintenant, vous pouvez ajouter votre SwoopPanel directement au modèle de contrôle et, en utilisant la propriété, le marquer comme l'ItemsHost que l'ItemsControl mettra tous les éléments en modèle qu'il crée.

  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="ItemsControl">
        <Border CornerRadius="5">
          <ScrollViewer VerticalScrollBarVisibility="Hidden">
            <lol:SwoopPanel IsItemsHost="True"/>
          </ScrollViewer>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>

Devez-vous le faire d'une manière ou d'une autre? Non. Est-ce qu'une est plus avantageuse que l'autre? Eh bien, la deuxième façon vous permet de mieux contrôler l'interface utilisateur, la première façon est plus facile. À vous de choisir, vraiment. Personnellement, je ne l'ai jamais fait de la deuxième manière, mais je pense qu'il pourrait y avoir quelques endroits où cela pourrait être utile.

0 votes

Donc, en gros, le code ItemsControl prendra note du contrôle défini comme IsItemsHost dans sa hiérarchie, et s'il n'y a pas de ItemsPanelTemplate définie, utilisera cet enfant comme conteneur pour les enfants générés ? (Je suppose qu'il est possible que cela provoque une erreur si vous avez un template ET un enfant IsItemsHost).

1 votes

EstItemsHost n'est pas une propriété attachée

1 votes

@kai merci pour la mise à jour. Semble être un bon candidat; il est un peu étrange que le Panel sache comment ItemsControl est implémenté.

16voto

MarqueIV Points 4268

Plus d'explications, s'il vous plaît!

Alors que toutes les réponses ci-dessus sont techniquement correctes, je pense qu'elles n'illustrent pas comment IsItemsPanel se rapporte au ControlTemplate et à la présence (ou à l'absence) d'un ItemsPresenter et de la propriété correspondante ItemsPanel qu'il utilise. Cette réponse tentera d'éclairer ces aspects et espère clarifier quand vous devriez, ou ne devriez pas utiliser chacun.

ItemsControls, Panels et IsItemsHost, Oh mon dieu!

Un ItemsControl est simplement un contrôle qui affiche une collection d'éléments. Il le fait en générant d'abord des conteneurs individuels* pour représenter visuellement les éléments, puis il remet ces conteneurs à un panel spécifique pour les agencer pour être affichés à l'écran. Lorsque des éléments sont ajoutés ou supprimés, l' ItemsControl ajoute ou supprime les conteneurs correspondants du panel selon le besoin.

* Note: Si un élément est déjà une instance du type de conteneur (tel que déterminé par le résultat du remplacement de la méthode IsItemItsOwnContainer du ItemsControl) -- c'est-à-dire, vous ajoutez une instance de ListBoxItem à la collection Items d'une ListBox -- cet élément est simplement transmis en l'état directement au panel, agissant comme son propre conteneur.

Le panel spécifique utilisé pour héberger et agencer les conteneurs est le premier panel trouvé dans le modèle de contrôle de l' ItemControl qui a sa propriété IsItemsHost définie sur 'True'.

Il y a deux façons de spécifier lequel il s'agit:

  1. En insérant un ItemsPresenter dans le ControlTemplate pour servir de substitut au panel spécifié par la propriété ItemsPanel. (C'est la manière la plus courante.)

  2. En insérant directement un Panel dans le ControlTemplate et en définissant explicitement sa propriété IsItemsHost sur True.

Mais lequel utiliser et pourquoi? Continuez à lire pour le découvrir!

ItemsPresenter - "Faites comme bon vous semble!"

Dans un ControlTemplate typique pour un ItemsControl tel qu'une ListBox, le modèle spécifie un ItemsPresenter quelque part à l'intérieur de celui-ci. Voici un extrait simplifié montrant comment il est utilisé:

Comme vous pouvez le voir, il y a un ItemsPresenter spécifié à l'intérieur d'un ScrollViewer au milieu du modèle. Ce que vous ne voyez cependant pas, c'est un panel réel pour agencer les éléments.

Alors, s'il n'y a pas de panel défini dans le modèle, d'où vient-il? C'est là que la propriété ItemsPanel entre en jeu. Comme son nom l'indique, cette propriété définit quel panel sera utilisé pour héberger et agencer les éléments. Cependant, elle ne dit pas où ce panel apparaît dans le ControlTemplate.

Cela nous ramène à l'ItemsPresenter. En bref, c'est un substitut qui dit essentiellement "Lorsque la propriété ItemsPanel est définie, j'insérerai ce panel ici et définirai automatiquement son IsItemsHost sur True."

L'avantage d'utiliser un ItemsPresenter dans le modèle de votre ItemsControl est que vous rendez très facile pour les consommateurs de votre contrôle de remplacer ce panel sans avoir à restructurer complètement l'intégralité de votre contrôle.

IsItemsHost - "A ma manière ou la route!"

Cependant, que se passe-t-il si vous ne souhaitez pas que quelqu'un puisse remplacer votre panel parce que votre contrôle dépend d'une implémentation de panel personnalisée et que tout autre chose cassera la fonctionnalité? Dans ce cas, vous n'utilisez pas un ItemsPresenter dans votre modèle. Vous devez plutôt spécifier le panel exact que vous souhaitez utiliser.

C'est là que la propriété IsItemsHost entre en jeu. Lorsqu'elle est définie sur un panel dans le ControlTemplate, elle indique à cet ItemsControl d'utiliser ce panel spécifique pour héberger les conteneurs générés, indépendamment de ce que la propriété ItemsPanel est définie. La propriété ItemsPanel est essentiellement ignorée.

Un autre avantage de spécifier le panel directement dans le modèle est que vous pouvez ensuite le nommer et y accéder comme n'importe quelle autre partie du modèle.

Voici le même exemple que ci-dessus, mais au lieu d'un ItemsPresenter, il code en dur un SpecializedPanel pour agencer les éléments. Nous indiquons que c'est le panel que nous voulons utiliser pour héberger les éléments en définissant sa propriété IsItemsHost sur True et enfin, lui donnons un nom pour y accéder directement depuis le code.

Dans ce cas, puisque le modèle n'utilise pas un ItemsPresenter et inclut directement un panel avec sa propriété IsItemsHost définie sur True, il n'y a aucun moyen pour l'utilisateur de remplacer ce panel autrement que par le remplacement complet du ControlTemplate entier. (Comme mentionné précédemment, la propriété ItemsPanel est ignorée.)

En concluant...

Pour récapituler, si vous êtes l'auteur d'un contrôle et souhaitez donner aux consommateurs de votre contrôle la flexibilité de remplacer le panel utilisé pour agencer vos éléments, alors définissez votre modèle pour votre ItemsControl en utilisant un ItemsPresenter. Assurez-vous également de définir la propriété ItemsPanel dans le modèle pour spécifier un panel par défaut.

Cependant, si vous souhaitez 'verrouiller' le panel utilisé par votre contrôle, alors n'utilisez pas un ItemsPresenter dans le ControlTemplate. Au lieu de cela, spécifiez le panel spécifique que vous souhaitez utiliser directement dans le modèle, puis définissez sa propriété IsItemsHost sur True.

Note: Il existe techniquement un troisième scénario, qui est probablement plus courant: Vous n'êtes pas un auteur de contrôle créant quelque chose à être consommé par d'autres utilisateurs, mais vous restructurez simplement un ItemsControl (comme par exemple une ListBox) pour une utilisation spécialisée dans votre propre application.

Dans ce cas, étant donné que vous êtes le consommateur ultime du contrôle, il est fort probable que vous n'aurez pas à vous soucier d'autres consommateurs en aval ayant besoin de changer le panel, il est tout à fait acceptable de simplement spécifier le panel directement dans votre modèle (encore une fois, en définissant IsItemsHost à true) et de ne pas vous soucier d'utiliser un ItemsPresenter et sa propriété associée ItemsPanel car cette dernière, bien que valide, ajouterait simplement une complexité inutile sans aucun réel bénéfice.

En espérant que cela clarifie exactement ce qui se passe.

12voto

Richard Points 11

Consultez http://msdn.microsoft.com/en-us/library/system.windows.controls.panel.isitemshost(v=vs.90).aspx

Fondamentalement, ce message dit que si vous remplacez le ControlTemplate d'un ListBox et que vous voulez une nouvelle disposition, définissez IsItemsHost=true sur un panel, par exemple un StackPanel. Ensuite, tous les éléments du ListBox seront automatiquement ajoutés en tant qu'enfants du StackPanel. Si l'orientation du ListBox est horizontale, alors le ListBox sera horizontal.

L'autre méthode consiste à définir la propriété ItemsPanel du ListBox sur un ItemsTemplate et dans ce modèle, vous avez un StackPanel. Dans ce cas, les éléments du ListBox seront ajoutés aux enfants du StackPanel comme dans le premier cas. Cependant, vous n'avez pas besoin de définir IsItemsHost = true, cela n'aura absolument aucun effet. Cela est fait pour vous par le fait que vous définissez la propriété ItemsPanel.

1 votes

C'est l'explication +1

0 votes

Presque! :) Il n'y a rien qui dit que vous devez utiliser IsItemsHost dans un ControlTemplate personnalisé. C'est juste plus facile si vous le faites. Mais vous pouvez toujours utiliser la combinaison ItemsPresenter/ItemsPanel si, par exemple, vous re-stylisez le chrome autour du panneau lui-même, mais ne voulez pas affecter la capacité des autres à changer ce panneau. Vous pouvez consulter ma réponse pour plus d'éclaircissements sur la manière dont ils se corrélatent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X