Forcing WPF para criar os itens em um ItemsControl
Quero verificar se os itens no meuListBox
são exibidos corretamente na interface do usuário. Imaginei que uma maneira de fazer isso é passar por todos os filhos doListBox
na árvore visual, obtenha o texto e compare-o com o que espero que seja o text
O problema dessa abordagem é que internamenteListBox
usa umVirtualizingStackPanel
para exibir seus itens, para que apenas os itens visíveis sejam criados. Acabei encontrando oItemContainerGenerator
class, que parece forçar o WPF a criar os controles na árvore visual para o item especificado. Infelizmente, isso está causando alguns efeitos estranhos para mim. Aqui está o meu código para gerar todos os itens noListBox
:
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 fornecer o código paraGetItemText()
se você quiser, mas ele simplesmente percorre a árvore visual até que umTextBlock
seja encontrado. Percebo que existem outras maneiras de inserir texto em um item, mas corrigirei isso assim que a geração de itens estiver funcionando corretamente.)
No meu aplicativo,ItemsListBox
contém 20 itens, com os 12 primeiros itens visíveis inicialmente. O texto para os primeiros 14 itens está correto (provavelmente porque seus controles já foram gerados). No entanto, para os itens 15-20, não recebo nenhum texto. Além disso, se eu rolar até a parte inferior doItemsListBox
, o texto dos itens 15-20 também está em branco. Parece que estou interferindo no mecanismo normal do WPF para gerar controles de alguma maneir
O que estou fazendo de errado? Existe uma maneira diferente / melhor de forçar os itens em umItemsControl
a ser adicionado à árvore visual?
Atualiza: Acho que descobri por que isso está ocorrendo, embora não saiba como corrigi-lo. Suponho que a chamada paraPrepareItemContainer()
geraria os controles necessários para exibir o item e adicionaria o contêiner à árvore visual no local correto. Acontece que não está fazendo nenhuma dessas coisas. O contêiner não é adicionado aoItemsControl
até rolar para baixo para visualizá-lo e, naquele momento, apenas o próprio contêiner (ou seja,ListBoxItem
) é criado - seus filhos não são criados (deve haver alguns controles adicionados aqui, um dos quais deve ser oTextBlock
que exibirá o texto do item
Se eu percorrer a árvore visual do controle para o qual passeiPrepareItemContainer()
os resultados são os mesmos. Nos dois casos, apenas oListBoxItem
é criado e nenhum de seus filhos é criad
Não foi possível encontrar uma boa maneira de adicionar oListBoxItem
para a árvore visual. Eu encontrei oVirtualizingStackPanel
na árvore visual, mas chamando seuChildren.Add()
resulta em umInvalidOperationException
(não é possível adicionar itens diretamente aoItemPanel
, pois gera itens para seuItemsControl
). Apenas como teste, tentei chamar seuAddVisualChild()
usando Reflection (uma vez que está protegido), mas também não funciono