Desidero verificare che gli elementi nel mio ListBox
siano visualizzati correttamente nell'interfaccia utente. Ho capito che un modo per farlo è quello di passare attraverso tutti i bambini dello ListBox
nell'albero visivo, ottenere il loro testo e quindi confrontarlo con quello che mi aspetto che il testo sia.Forzare WPF per creare gli elementi in un ItemsControl
Il problema con questo approccio è che internamente ListBox
utilizza uno VirtualizingStackPanel
per visualizzare i suoi elementi, quindi vengono creati solo gli elementi visibili. Alla fine mi sono imbattuto nella classe ItemContainerGenerator
, che sembra debba costringere WPF a creare i controlli nella struttura visiva per l'elemento specificato. Sfortunatamente, ciò sta causando alcuni strani effetti collaterali per me. Ecco il mio codice per generare tutti gli elementi nella 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);
}
}
(posso fornire il codice per GetItemText()
se vuoi, ma semplicemente attraversa la struttura ad albero visuale fino a quando un TextBlock
è trovato mi rendo conto ci sono altri modi per avere un testo in un articolo, ma lo aggiusterò una volta che avrò funzionato correttamente.)
Nella mia app, ItemsListBox
contiene 20 articoli, con i primi 12 elementi inizialmente visibili. Il testo per i primi 14 elementi è corretto (probabilmente perché i loro controlli sono già stati generati). Tuttavia, per gli articoli 15-20, non ottengo alcun testo. Inoltre, se si scorre verso il basso dello ItemsListBox
, anche il testo degli elementi 15-20 è vuoto. Quindi sembra che io stia interferendo con il normale meccanismo di WPF per la generazione dei controlli.
Cosa sto sbagliando? C'è un modo diverso/migliore di forzare gli oggetti in un ItemsControl
da aggiungere all'albero visivo?
Aggiornamento: Penso di aver scoperto perché si sta verificando, anche se non so come risolverlo. Suppongo che la chiamata a PrepareItemContainer()
generi tutti i controlli necessari per visualizzare l'elemento e quindi aggiungere il contenitore all'albero visivo nella posizione corretta. Si scopre che non sta facendo nessuna di queste cose. Il contenitore non viene aggiunto allo ItemsControl
finché non si scorre verso il basso per visualizzarlo e in quel momento viene creato solo il contenitore stesso (ad esempio ListBoxItem
) - i suoi figli non vengono creati (ci dovrebbero essere alcuni controlli aggiunti qui, uno dei quali dovrebbe essere il TextBlock
che visualizzerà il testo dell'articolo).
Se attraverso l'albero visivo del controllo che ho passato a PrepareItemContainer()
i risultati sono gli stessi. In entrambi i casi viene creato solo lo ListBoxItem
e nessuno dei suoi figli viene creato.
Non sono riuscito a trovare un buon modo per aggiungere ListBoxItem
all'albero visivo. Ho trovato il VirtualizingStackPanel
nell'albero visivo, ma chiamando i suoi risultati Children.Add()
in un InvalidOperationException
(non è possibile aggiungere elementi direttamente allo ItemPanel
, poiché genera elementi per il suo ItemsControl
). Proprio come un test, ho provato a chiamare il suo AddVisualChild()
usando Reflection (dato che è protetto), ma non ha funzionato.
Non capisco. Perché vuoi farlo? Prove? –
Sì, solo a scopo di test. – Andy
È possibile impostare la proprietà ['VirtualizingStackPanel.IsVirtualizing'] (http://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingstackpanel.isvirtualizing.aspx) associata a' false' in 'ItemsListBox 'prima di aggiungere gli articoli. Quando lo imposti a 'true' di nuovo, le cose inizieranno a virtualizzare quando scorri. –