WPF ItemsControl - 如何知道项目何时完成加载,以便我可以集中第一个?

时间:2010-03-22 12:39:41

标签: wpf focus itemscontrol loaded

我的View中有一个ItemsControl,它绑定到ViewModel的ObservableCollection。该集合已填满,之后会引发从VM到视图的事件(想想搜索结果和SearchFinished事件)。

我想将键盘焦点移动到ItemsControl中的第一个项目,但是当我在处理SearchFinished时在View的代码隐藏中执行它时,项目尚未呈现(集合已经填充,但是wpf的呈现是异步的)并且还没有发生),所以没有什么可以聚焦(Focus()需要已经构建了项目的可视树)。

我想(myItemsControl.ItemContainerGenerator.ContainerFromIndex(0)作为UIElement).Focus();,但由于第0项尚未加载,ContainerFromIndex(0)返回null。

我尝试使用低优先级的Dispatcher.BeginInvoke延迟它,但这取决于确切的时间并且通常不起作用。

如何等待ItemsControl中的第一项加载?

2 个答案:

答案 0 :(得分:8)

您可以使用ItemContainerGenerator.StatusChanged事件,然后检查其Status属性。如果是Status == GeneratorStatus.ContainersGenerated,那么您可以安全地获得第一个容器。

答案 1 :(得分:0)

在我的应用中,我发现 ItemContainerGenerator.StatusChangedStatus == GeneratorStatus.ContainersGenerated 与屏幕明显呈现的时刻不一致。实际上,在渲染大量项目时会出现相当大的延迟;此延迟发生在 ContainersGenerated 报告之后。

相反,我发现等待 ItemsPresenter.Loaded 事件效果更好。此事件似乎与渲染完成以及 UI 的非忙碌状态更接近。

由于 ItemsPresenterListBox(或通常的 ItemsControl)的控制模板的一部分,您可能必须重新定义该模板才能获得它。就我而言,无论如何我都有一个自定义模板,所以效果很好。

特别是在我的情况下,我使用的是 MultiSelector,但就我所知,这个问题与 ItemsControlListBox 没有什么不同:< /p>

<MultiSelector
   ItemsSource="{Binding ...}"
   >

   <MultiSelector.Template>
      <ControlTemplate TargetType="{x:Type MultiSelector}">
        <ScrollViewer>
            <ItemsPresenter Loaded="ItemsPresenter_Loaded"/>
        </ScrollViewer>
    </ControlTemplate>
</MultiSelector.Template>

...

或者,您可能可以搜索可视化树以找到 ItemsPresenter。