8

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

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

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

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

如何等到 ItemsControl 中的第一个项目被加载?

4

2 回答 2

9

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

于 2010-03-22T13:37:27.343 回答
0

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

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

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

特别是在我的情况下,我使用的是 a ,但据我所知,就MultiSelector这个问题而言,它与ItemsControlor没有什么不同:ListBox

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

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

...

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

于 2021-03-08T18:54:32.730 回答