ItemContainerGenerator

ItemContainerGenerator

在我的应用程序中,我需要在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。我仍然非常想知道是否有人解决了这个问题。

最佳答案

几分钟前,我遇到了同样的问题。几乎没有什么不同,我需要项目容器的确切位置和大小信息。我尝试过尝试尝试监听StatusChangedItemContainerGenerator事件,最后发现状态变为ContainersGenerated并且确实生成了容器时,它们尚未布置。

所以我做了一些非常粗鲁的事。首先,我设置一个标志,例如_updatePending,而ItemContainerGenerator的状态变为ContainersGenerated,然后我处理了LayoutUpdatedItemsControl事件,该事件会频繁触发,以检查标志以及项目容器是否布置:

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/

10-13 06:02