私の項目がListBoxUI で正しく表示されることを確認したいと思います。これを行う 1 つの方法はListBox、ビジュアル ツリー内の のすべての子を調べてテキストを取得し、それを期待するテキストと比較することだと考えました。
このアプローチの問題点は、内部的ListBoxに a を使用しVirtualizingStackPanelてアイテムを表示するため、表示されているアイテムのみが作成されることです。私は最終的にクラスに出くわしましたItemContainerGenerator。これは、指定された項目のビジュアル ツリーにコントロールを作成するように WPF に強制するように見えます。残念ながら、それは私にいくつかの奇妙な副作用を引き起こしています. のすべてのアイテムを生成するコードは次の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);
}
}
(必要に応じて のコードを提供できますがGetItemText()、 が見つかるまでビジュアル ツリーをトラバースするだけTextBlockです。アイテムにテキストを含める方法は他にもあると思いますが、アイテムを取得したら修正します。世代は正常に動作しています。)
私のアプリでItemsListBoxは、最初に表示される最初の 12 項目で、20 項目が含まれています。最初の 14 項目のテキストは正しいです (それらのコントロールが既に生成されている可能性があります)。ただし、項目 15 ~ 20 については、テキストがまったく表示されません。さらに、一番下までスクロールすると、ItemsListBox項目 15 ~ 20 のテキストも空白になります。したがって、何らかの方法でコントロールを生成するための WPF の通常のメカニズムに干渉しているようです。
私は何を間違っていますか?ItemsControlアイテムを強制的にビジュアル ツリーに追加する別の/より良い方法はありますか?
更新:修正方法はわかりませんが、これが発生する理由はわかったと思います。PrepareItemContainer()への呼び出しにより、アイテムを表示するために必要なコントロールが生成され、コンテナーがビジュアル ツリーの正しい場所に追加されると仮定しました。これらのことのいずれも行っていないことが判明しました。コンテナは、下にスクロールして表示するまで追加されません。ItemsControlその時点では、コンテナ自体(つまりListBoxItem)のみが作成されます-その子は作成されません(ここにいくつかのコントロールが追加され、そのうちの1つがアイテムのTextBlockテキストを表示します)。
結果に渡したコントロールのビジュアル ツリーをトラバースするとPrepareItemContainer()、結果は同じになります。どちらの場合も、 のみListBoxItemが作成され、その子は作成されません。
ListBoxItemをビジュアル ツリーに追加する良い方法が見つかりませんでした。ビジュアル ツリーでを見つけましたVirtualizingStackPanelが、そのChildren.Add()結果を で呼び出します ( の項目を生成するため、InvalidOperationException項目を に直接追加することはできません)。テストとして、リフレクションを使用して呼び出してみましたが(保護されているため)、それも機能しませんでした。ItemPanelItemsControlAddVisualChild()