我有一个ListBox,我需要将其ControlTemplate设置为Virtualizing WrapPanel,这是一个使用如下样式扩展VirtualizingPanel的类:
<Style TargetType="{x:Type ListBox}" x:Key="PhotoListBoxStyle">
<Setter Property="Foreground" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}" >
<s:VirtualizingVerticalWrapPanel>
</s:VirtualizingVerticalWrapPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
现在,在下面虚拟化WrapPanel的私有方法中,我尝试访问this.ItemContainerGenerator,但是我得到null值,任何想法是什么问题?
private void RealizeFirstItem()
{
IItemContainerGenerator generator = this.ItemContainerGenerator;
GeneratorPosition pos = generator.GeneratorPositionFromIndex(0);
using (generator.StartAt(pos, GeneratorDirection.Forward))
{
UIElement element = generator.GenerateNext() as UIElement;
generator.PrepareItemContainer(element);
this.AddInternalChild(element);
}
}
答案 0 :(得分:7)
我认为我遇到了类似的问题,这有助于:
var necessaryChidrenTouch = this.Children;
IItemContainerGenerator generator = this.ItemContainerGenerator;
...由于某种原因,您必须“触摸”子集合才能使ItemContainerGenerator正确初始化。
答案 1 :(得分:2)
对于Windows 8.1 Metro应用程序,ItemContainerGenerator已被删除,并将返回null。新的Apis:
ItemsControl.ItemContainerGenerator.ItemFromContainer = ItemsControl.ItemFromContainer
ItemsControl.ItemContainerGenerator.ContainerFromItem = ItemsControl.ContainerFromItem
ItemsControl.ItemContainerGenerator.IndexFromContainer = ItemsControl.IndexFromContainer
ItemsControl.ItemContainerGenerator.ContainerFromIndex = ItemsControl.ContainerFromIndex
http://msdn.microsoft.com/en-us/library/windows/apps/dn376326.aspx
答案 2 :(得分:0)
Falck大多是正确的。实际上,您需要引用虚拟化堆栈面板的“InternalChildren”。此属性的反编译代码为:
protected internal UIElementCollection InternalChildren
{
get
{
this.VerifyBoundState();
if (this.IsItemsHost)
{
this.EnsureGenerator();
}
else if (this._uiElementCollection == null)
{
this.EnsureEmptyChildren(this);
}
return this._uiElementCollection;
}
}
'EnsureGenerator'负责确保发电机可用。非常差的'及时'设计,IMO。
答案 3 :(得分:0)
很可能这是与虚拟化相关的问题,因此仅为当前可见的项目生成ListBoxItem
容器(例如https://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingstackpanel(v=vs.110).aspx#Anchor_9)
我建议切换到ListView
而不是ListBox
- 它继承自ListBox
,它支持ScrollIntoView()
方法,您可以利用它来控制虚拟化;
targetListView.ScrollIntoView(itemVM);
DoEvents();
ListViewItem itemContainer = targetListView.ItemContainerGenerator.ContainerFromItem(itemVM) as ListViewItem;
(上面的示例还使用了此处详细说明的DoEvents()
静态方法; WPF how to wait for binding update to occur before processing more code?)
ListBox
和ListView
控件(What is The difference between ListBox and ListView)之间存在一些其他细微差别 - 这不一定会影响您的使用案例。
答案 4 :(得分:-1)
这是因为您更改了列表框的模板,而您应该刚刚更改了ItemsPanel:
<ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<s:VirtualizingVerticalWrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>