在我的应用程序中,我需要在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
返回的容器不为空。但是,VisualTreeHelper.GetChildrenCount(container)
为0.我仍然非常想知道是否有人解决了这个问题。
答案 0 :(得分:3)
几分钟前我遇到了同样的问题。一些小的区别是,我需要物品容器的确切位置和尺寸信息。我尝试过你试图听StatusChanged
的{{1}}事件,最后发现当状态变为ItemContainerGenerator
且容器确实生成时,它们还没有布局。
所以我做了一些非常粗暴的事情。首先,我设置了一个标记,例如ContainersGenerated
,而_updatePending
的状态变为ItemContainerGenerator
,然后我处理了ContainersGenerated
的{{1}}事件,会频繁开火,检查LayoutUpdated
标志以及项目容器是否布局:
ItemsControl
这是残酷的,但不知何故有效。
答案 1 :(得分:0)
问题是您在更改集合时无法迭代它。解决此问题的一种方法是在填充数据后直接查看ItemsSource对象,而不是尝试迭代控件上的ItemsSource。如果您使用的是MVVVM模式,则应该能够在ViewModel中填充集合属性(绑定到控件的ItemsSource的属性),并在从数据库/服务返回数据后进行检查。