在我的应用程序中,我需要在ItemsSource更改后立即获取ItemsCollection的内容。或者,至少在视觉上绘制内容之前。
我测试了以下内容:
void UserControl_Loaded(object sender, EventArgs eventArgs) {
this.itemsControl.ItemsSource = GetItemsSource();
int ctrIndex = 0;
DependencyObject container;
while((container = this.itemsControl.ItemContainerGenerator.
ContainerFromIndex(ctrIndex++)) != null) {
DoSomething(VisualTreeHelper.GetChild(container, 0));
}
}
问题在于,在调用DoSomething时,
VisualTreeHelper.GetChildrenCount(container)
的值为0
。如果改为在以后的某个时间调用此代码(例如,响应于Button.Click
事件触发),则VisualTreeHelper.GetChildrenCount
是期望值,并且该代码可能会正常工作。PS。我还尝试在匿名函数内部进行while循环:
this.itemsControl.ItemContainerGenerator.ItemsChanged += (_sender, _ea) => {
int ctrIndex = 0;
DependencyObject container;
while((container = this.itemsControl.ItemContainerGenerator.
ContainerFromIndex(ctrIndex++)) != null) {
DoSomething(VisualTreeHelper.GetChild(container, 0));
}
};
可悲的是,行为是相同的。
编辑
我不敢相信您必须为生成的内容跳过几圈。
我相信我已经找到了可以安全捕获生成的容器的最早时间。但是,我仍然对那些容器内生成的内容不加关注。请注意以下几点:
this.itemsControl.ItemContainerGenerator.StatusChanged += new EventHandler(StatusChanged);
void StatusChanged(object sender, EventArgs e) {
var cg = this.itemsControl.ItemContainerGenerator;
if(cg.Status == GeneratorStatus.ContainersGenerated && cg.ContainerFromIndex(0) != null) {
DoStuff();
}
}
在调用DoStuff()时,从
ContainerFromIndex
返回的容器不为null。但是,VisualTreeHelper.GetChildrenCount(container)
为0。我仍然非常想知道是否有人解决了这个问题。 最佳答案
几分钟前,我遇到了同样的问题。几乎没有什么不同,我需要项目容器的确切位置和大小信息。我尝试过尝试尝试监听StatusChanged
的ItemContainerGenerator
事件,最后发现状态变为ContainersGenerated
并且确实生成了容器时,它们尚未布置。
所以我做了一些非常粗鲁的事。首先,我设置一个标志,例如_updatePending
,而ItemContainerGenerator
的状态变为ContainersGenerated
,然后我处理了LayoutUpdated
的ItemsControl
事件,该事件会频繁触发,以检查标志以及项目容器是否布置:
var firstContainer = this.ItemsContainer.ItemContainerGenerator.ContainerFromIndex(0) as FrameworkElement;
if (_updatePending
&& firstContainer != null
&& firstContainer.IsLoaded)
{
// do stuff
_updatePending = false;
}
这是残酷的,但以某种方式有效。
关于c# - WPF ItemsCollection.ItemContainerGenerator的可能竞争条件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4672315/