为什么ItemContainerGenerator返回null?
我有一个列表框,我需要它的控件模板设置为虚拟WrapPanel这是一个扩展VirtualizingPanel,使用样式,看起来像这样一类:为什么ItemContainerGenerator返回null?
<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,但我得到空值,任何想法有什么问题?
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);
}
}
我想我也有类似的问题,这有助于:
var necessaryChidrenTouch = this.Children;
IItemContainerGenerator generator = this.ItemContainerGenerator;
...由于某种原因,你必须以“触摸”孩子们收集了ItemContainerGenerator正确初始化。
不知道你为什么被低估,按照我的经验你是绝对正确的。这是一个早在5年前由Avalon团队成员注意到的错误。 – Jordan0Day 2011-06-08 16:09:51
完美,谢谢! – Andy 2013-03-04 11:47:53
这是因为你改变了ListBox的模板,而ü应该有只是改变了ItemsPanel:
<ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<s:VirtualizingVerticalWrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
法尔克大多是正确的。实际上,你需要引用虚拟化堆栈面板的'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)非常糟糕的“及时”设计。
对于Windows 8.1 Metro应用程序,ItemContainerGenerator被取消并返回null。新的API:
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
非常感谢先生 – FatemehEbrahimiNik 2016-05-21 07:36:14
很可能这是一个虚拟化相关问题,所以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)差异 - 这不应该基本上影响你的用例。
“this.ItemContainerGenerator”是否意味着Listbox? – Ragunathan 2010-07-20 12:02:16
这是指Virtualizing WrapPanel,虚拟化WrapPanel用在ListBox的ControlTemplate中 – simo 2010-07-22 06:52:37