【问题标题】:WPF ItemsControl - how to know when the items finished loading, so that I can focus the first one?WPF ItemsControl - 如何知道项目何时完成加载,以便我可以关注第一个?
【发布时间】:2011-01-30 08:04:59
【问题描述】:

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

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

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

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

我怎样才能等到 ItemsControl 中的第一个项目被加载?

【问题讨论】:

    标签: wpf focus itemscontrol loaded


    【解决方案1】:

    您可以使用ItemContainerGenerator.StatusChanged 事件,然后检查其Status 属性。如果是Status == GeneratorStatus.ContainersGenerated,那么就可以放心的拿到第一个容器了。

    【讨论】:

      【解决方案2】:

      在我的应用程序中,我发现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。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多