WPF ItemsControl - 如何知道项目何时加载完成,以便我可以将焦点放在第一个项目上?

8

我在视图中有一个ItemsControl,它绑定到ViewModel中的ObservableCollection。集合已填充,并且随后从VM到View引发事件(考虑搜索结果和SearchFinished事件)。

我想将键盘焦点移动到ItemsControl中的第一项,但当我在View的代码后台处理SearchFinished时执行此操作时,尚未呈现项(集合已经填充,但wpf的呈现是异步的,尚未发生),因此没有什么可聚焦(Focus()需要已构建项的可视树)。

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

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

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

2个回答

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

0
在我的应用程序中,我发现当屏幕被可见地渲染时,ItemContainerGenerator.StatusChangedStatus == GeneratorStatus.ContainersGenerated并不一致。实际上,当大量项目被渲染时,存在相当大的延迟;这个延迟发生在报告ContainersGenerated之后。
相反,我发现等待ItemsPresenter.Loaded事件效果更好。这个事件似乎更接近于渲染完成和UI处于非繁忙状态。
由于ItemsPresenterListBox(或ItemsControl)的控件模板的一部分,您可能需要重新定义该模板才能获得它。在我的情况下,我已经有一个自定义模板,所以这个方法很好用。
特别是在我的情况下,我正在使用MultiSelector,但就我所知,在这个问题上它与ItemsControlListBox没有什么区别。
<MultiSelector
   ItemsSource="{Binding ...}"
   >

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

...

或者,您可以搜索可视树以查找ItemsPresenter。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接