Quiero verificar que los elementos en mi ListBox
se muestran correctamente en la interfaz de usuario. Pensé que una forma de hacerlo es revisar todos los elementos secundarios del ListBox
en el árbol visual, obtener su texto y compararlo con lo que esperaba que fuera el texto.Forzar WPF para crear los elementos en un ItemsControl
El problema con este enfoque es que internamente ListBox
usa un VirtualizingStackPanel
para mostrar sus elementos, por lo que solo se crean los elementos que están visibles. Finalmente me encontré con la clase ItemContainerGenerator
, que parece que debería obligar a WPF a crear los controles en el árbol visual para el elemento especificado. Desafortunadamente, eso está causando algunos efectos secundarios extraños para mí. Aquí está mi código para generar todos los elementos en el 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);
}
}
(puedo proporcionar el código de GetItemText()
si lo desea, pero simplemente atraviesa el árbol visual hasta que un TextBlock
se encontró que dan cuenta hay otras maneras de tener texto en un artículo, pero lo arreglaré una vez que la generación de elementos funcione correctamente.)
En mi aplicación, ItemsListBox
contiene 20 elementos, con los primeros 12 elementos inicialmente visibles. El texto de los primeros 14 elementos es correcto (probablemente porque sus controles ya se han generado). Sin embargo, para los puntos 15-20, no recibo ningún texto. Además, si me desplazo hacia la parte inferior de ItemsListBox
, el texto de los elementos 15-20 también está en blanco. Parece que estoy interfiriendo con el mecanismo normal de WPF para generar controles.
¿Qué estoy haciendo mal? ¿Hay una forma diferente/mejor de forzar los elementos en un ItemsControl
para ser agregados al árbol visual?
Actualización: Creo que he encontrado por qué ocurre esto, aunque no sé cómo solucionarlo. Mi suposición de que la llamada al PrepareItemContainer()
generaría los controles necesarios para mostrar el artículo, y luego agregaría el contenedor al árbol visual en la ubicación correcta. Resulta que no está haciendo ninguna de estas cosas. El contenedor no se agrega al ItemsControl
hasta que me desplazo hacia abajo para verlo, y en ese momento solo se crea el contenedor en sí (es decir, ListBoxItem
) - sus hijos no se crean (debe haber algunos controles agregados aquí, uno de los cuales debería ser el TextBlock
que mostrará el texto del elemento).
Si recorro el árbol visual del control que pasé al PrepareItemContainer()
, los resultados son los mismos. En ambos casos, solo se crea el ListBoxItem
y no se crea ninguno de sus elementos secundarios.
No pude encontrar una buena manera de agregar el ListBoxItem
al árbol visual. Encontré el VirtualizingStackPanel
en el árbol visual, pero llamando a su Children.Add()
da como resultado un InvalidOperationException
(no se pueden agregar elementos directamente al ItemPanel
, ya que genera elementos para su ItemsControl
). Solo como prueba, intenté llamar a su AddVisualChild()
usando Reflection (ya que está protegido), pero tampoco funcionó.
No entiendo. ¿Por qué quieres hacer esto? ¿Pruebas? –
Sí, solo para fines de prueba. – Andy
Puede establecer la propiedad adjunta ['VirtualizingStackPanel.IsVirtualizing'] (http://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingstackpanel.isvirtualizing.aspx) en' false' en 'ItemsListBox 'antes de agregar los artículos. Cuando lo ajuste a 'true 'de nuevo, las cosas comenzarán a virtualizarse cuando se desplace. –