8

ViewModel から ObservableCollection にバインドされているビューに ItemsControl があります。コレクションがいっぱいになり、その後、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.StatusChangedことがわかりました。Status == GeneratorStatus.ContainersGenerated実際、多数のアイテムがレンダリングされると、かなりの遅延が発生しました。この遅延は、ContainersGenerated報告された後でした。

代わりに、イベントを待つItemsPresenter.Loaded方がうまくいくことがわかりました。このイベントは、レンダリングの完了および UI の非ビジー ステータスとより密接に一致しているようです。

は(または一般に)ItemsPresenterのコントロール テンプレートの一部であるため、そのテンプレートを取得するには、そのテンプレートを再定義する必要がある場合があります。私の場合、とにかくカスタム テンプレートがあったので、うまくいきました。ListBoxItemsControl

具体的には、私の場合は を使用してMultiSelectorいましたが、この質問の目的のために、私が知る限り、ItemsControlまたはと違いはありません。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 に答える