首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WPF ItemsCollection.ItemContainerGenerator的可能竞赛条件

WPF ItemsCollection.ItemContainerGenerator的可能竞赛条件
EN

Stack Overflow用户
提问于 2011-01-12 18:11:36
回答 2查看 749关注 0票数 3

在我的应用程序中,我需要在更改ItemsCollection之后立即获取ItemsSource的内容。或者,至少,在内容被视觉绘制的可能性之前。

我测试了一些接近以下内容的内容:

代码语言:javascript
复制
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循环:

代码语言:javascript
复制
this.itemsControl.ItemContainerGenerator.ItemsChanged += (_sender, _ea) => {
    int ctrIndex = 0;
    DependencyObject container;
    while((container = this.itemsControl.ItemContainerGenerator.
        ContainerFromIndex(ctrIndex++)) != null) {

        DoSomething(VisualTreeHelper.GetChild(container, 0));
    }
};

不幸的是,这种行为是一样的。

编辑

我真不敢相信你要跳过多少圈才能得到生成的内容。

我相信我已经找到了能够安全捕获生成的容器的最早时刻。但是,我仍然对这些容器中生成的内容显示为零。观察以下情况:

代码语言:javascript
复制
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。我还是很想知道是否有人解决了这个问题。

EN

回答 2

Stack Overflow用户

发布于 2013-10-30 12:40:08

几分钟前我遇到了同样的问题。一些小的区别是,我需要准确的位置和大小的信息的项目容器。我试着听一听ItemContainerGeneratorItemContainerGenerator事件,最后发现虽然状态变成了ContainersGenerated,容器确实生成了,但它们还没有布局。

所以我做了件很粗暴的事。首先,我设置了一个标志,比如_updatePending,而ItemContainerGenerator的状态变成了ContainersGenerated,然后我处理了ItemsControlLayoutUpdated事件,这个事件会频繁地触发,以检查_updatePending标志以及项目容器是否布局:

代码语言:javascript
复制
var firstContainer = this.ItemsContainer.ItemContainerGenerator.ContainerFromIndex(0) as FrameworkElement;
if (_updatePending 
    && firstContainer != null 
    && firstContainer.IsLoaded)
{
    // do stuff
    _updatePending = false;
}

这是残酷的,但某种程度上是有效的。

票数 3
EN

Stack Overflow用户

发布于 2011-01-12 18:17:22

问题是,在对集合进行更改时,不能对其进行迭代。克服这一问题的一种方法是在填充数据之后直接查看ItemsSource对象,而不是在控件上迭代ItemsSource。如果使用的是MVVVM模式,则应该能够在ViewModel中填充集合属性(绑定到控件的ViewModel中的属性),并在从数据库/服务返回数据后检查该属性。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4672315

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档