Je souhaite vérifier que les éléments de mon ListBox
s'affichent correctement dans l'interface utilisateur. J'ai pensé qu'une façon de faire ceci est de passer en revue tous les enfants du ListBox
dans l'arbre visuel, d'obtenir leur texte, puis de comparer cela avec ce que j'attends du texte.Forcer WPF à créer les éléments dans ItemsControl
Le problème avec cette approche est qu'en interne ListBox
utilise un VirtualizingStackPanel
pour afficher ses éléments, de sorte que seuls les éléments visibles sont créés. J'ai finalement rencontré la classe ItemContainerGenerator
, qui semble devoir forcer WPF à créer les contrôles dans l'arborescence visuelle pour l'élément spécifié. Malheureusement, cela cause des effets secondaires bizarres pour moi. Voici mon code pour générer tous les éléments dans le ListBox
.
List<string> generatedItems = new List<string>();
IItemContainerGenerator generator = this.ItemsListBox.ItemContainerGenerator;
GeneratorPosition pos = generator.GeneratorPositionFromIndex(-1);
using(generator.StartAt(pos, GeneratorDirection.Forward))
{
bool isNewlyRealized;
for(int i = 0; i < this.ItemsListBox.Items.Count; i++)
{
isNewlyRealized = false;
DependencyObject cntr = generator.GenerateNext(out isNewlyRealized);
if(isNewlyRealized)
{
generator.PrepareItemContainer(cntr);
}
string itemText = GetControlText(cntr);
generatedItems.Add(itemText);
}
}
(je peux fournir le code pour GetItemText()
si vous le souhaitez, mais il traverse tout l'arbre visuel jusqu'à ce qu'un TextBlock
se trouve je réalise Il existe d'autres façons d'avoir du texte dans un élément, mais je le réparerai une fois que la génération d'éléments fonctionnera correctement.)
Dans mon application, ItemsListBox
contient 20 éléments, les 12 premiers éléments étant visibles au départ. Le texte pour les 14 premiers éléments est correct (probablement parce que leurs contrôles ont déjà été générés). Cependant, pour les articles 15 à 20, je n'ai aucun texte. En outre, si je fais défiler vers le bas du ItemsListBox
, le texte des articles 15-20 est également vide. Il semble donc que j'interfère avec le mécanisme normal de WPF pour générer des contrôles d'une certaine manière.
Qu'est-ce que je fais mal? Existe-t-il une manière différente/meilleure de forcer les éléments d'un ItemsControl
à être ajoutés à l'arborescence visuelle?
Mise à jour: Je pense que j'ai trouvé pourquoi cela se produit, même si je ne sais pas comment le réparer. Ma supposition que l'appel à PrepareItemContainer()
générerait les contrôles nécessaires pour afficher l'élément, puis ajouter le conteneur à l'arborescence visuelle à l'emplacement correct. Il s'avère qu'il ne fait aucune de ces choses. Le conteneur n'est pas ajouté au ItemsControl
jusqu'à ce que je défile vers le bas pour le voir, et à ce moment seul le conteneur lui-même (ListBoxItem
) est créé - ses enfants ne sont pas créés (il devrait y avoir quelques contrôles ajoutés ici, dont devrait être le TextBlock
qui affichera le texte de l'article).
Si je traverse l'arborescence visuelle du contrôle que j'ai passé à PrepareItemContainer()
, les résultats sont les mêmes. Dans les deux cas, seul le ListBoxItem
est créé et aucun de ses enfants n'est créé.
Je ne pouvais pas trouver un bon moyen d'ajouter le ListBoxItem
à l'arbre visuel. J'ai trouvé le VirtualizingStackPanel
dans l'arbre visuel, mais en appelant ses Children.Add()
les résultats dans un InvalidOperationException
(ne peut pas ajouter des articles directement au ItemPanel
, puisqu'il génère des articles pour son ItemsControl
). Tout comme un test, j'ai essayé d'appeler son AddVisualChild()
en utilisant la réflexion (car il est protégé), mais cela n'a pas fonctionné non plus.
Je ne comprends pas. Pourquoi voulez-vous faire cela? Essai? –
Oui - juste à des fins de test. – Andy
Vous pouvez définir la propriété attachée ['VirtualizingStackPanel.IsVirtualizing'] (http://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingstackpanel.isvirtualizing.aspx) à' false' sur 'ItemsListBox 'avant d'ajouter les éléments. Lorsque vous définissez à true, les choses vont commencer à virtualiser lorsque vous faites défiler. –