我想验证我的项目在ListBox
UI 中正确显示。我想一种方法是遍历ListBox
视觉树中的所有孩子,获取他们的文本,然后将其与我期望的文本进行比较。
这种方法的问题在于内部ListBox
使用 aVirtualizingStackPanel
来显示其项目,因此仅创建可见的项目。我最终遇到了这个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
找到 a。我意识到还有其他方法可以在项目中包含文本,但一旦我得到项目,我会修复一代工作正常。)
在我的应用程序中,ItemsListBox
包含 20 个项目,前 12 个项目最初可见。前 14 个项目的文本是正确的(可能是因为它们的控件已经生成)。但是,对于第 15-20 项,我根本没有收到任何文本。另外,如果我滚动到底部ItemsListBox
,第 15-20 项的文本也是空白的。因此,我似乎在干扰 WPF 生成控件的正常机制。
我究竟做错了什么?是否有一种不同/更好的方法可以强制将 anItemsControl
中的项目添加到可视化树中?
更新:我认为我已经找到了发生这种情况的原因,尽管我不知道如何解决它。我假设调用PrepareItemContainer()
将生成任何必要的控件来显示项目,然后将容器添加到正确位置的可视化树中。事实证明,它没有做这两件事。直到我向下滚动查看它,容器才被添加到ItemsControl
,当时只有容器本身(即ListBoxItem
)被创建 - 它的子级没有被创建(这里应该添加一些控件,其中一个应该是将TextBlock
显示项目的文本)。
如果我遍历我传递给PrepareItemContainer()
结果的控件的可视化树是相同的。在这两种情况下,都只ListBoxItem
创建了 ,而没有创建它的任何子项。
我找不到将其添加ListBoxItem
到可视化树的好方法。我VirtualizingStackPanel
在可视化树中找到了 ,但是Children.Add()
在 an 中调用了它的结果InvalidOperationException
(不能直接将项目添加到ItemPanel
,因为它会为其生成项目ItemsControl
)。作为测试,我尝试AddVisualChild()
使用反射调用它(因为它受到保护),但这也不起作用。