我想验证我的项目ListBox
是否在UI中正确显示.我认为这样做的一种方法是遍历ListBox
视觉树中的所有孩子,获取他们的文本,然后将其与我期望的文本进行比较.
这种方法的问题是内部ListBox
使用a VirtualizingStackPanel
来显示其项目,因此只创建可见的项目.我最终遇到了这个ItemContainerGenerator
类,它看起来应该强制WPF在可视树中为指定项创建控件.不幸的是,这对我造成了一些奇怪的副作用.这是我生成以下所有项目的代码ListBox
:
ListgeneratedItems = new List (); 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
包含20个项目,最初的12个项目最初可见.前14项的文本是正确的(可能是因为它们的控件已经生成).但是,对于第15-20项,我根本没有任何文字.另外,如果我滚动到底部ItemsListBox
,项目15-20的文本也是空白的.因此,我似乎正在干扰WPF生成控件的常规机制.
我究竟做错了什么?是否有一种不同/更好的方法可以强制将项ItemsControl
添加到可视树中?
更新:我认为我已经找到了为什么会发生这种情况,虽然我不知道如何解决它.我假设调用PrepareItemContainer()
将生成任何必要的控件来显示项目,然后将容器添加到可视树中的正确位置.事实证明,它没有做这两件事.容器没有被添加到ItemsControl
直到我向下滚动才能查看它,并且在那时只ListBoxItem
创建了容器本身(即) - 它的子节点没有被创建(这里应该添加一些控件,其中一个应该是在TextBlock
将显示该项目的文本).
如果我遍历控件的可视树,我传递给PrepareItemContainer()
结果是相同的.在这两种情况下,只ListBoxItem
创建了它,并且没有创建它的子节点.
我找不到添加ListBoxItem
到可视树的好方法.我VirtualizingStackPanel
在可视树中找到了它,但是调用了它的Children.Add()
结果InvalidOperationException
(不能直接添加项目ItemPanel
,因为它为它生成了项目ItemsControl
).就像测试一样,我尝试AddVisualChild()
使用Reflection 调用它(因为它受到保护),但这也没有用.