1. ホーム
  2. wpf

[解決済み] ItemsControlの仮想化?

2022-06-23 08:10:15

質問

私は ItemsControl には仮想化したいデータのリストが含まれています。 VirtualizingStackPanel.IsVirtualizing="True" では動作しないようです。 ItemsControl .

これは本当にそうなのでしょうか、それとも私の知らない別の方法があるのでしょうか?

テストするために、私はコードの次のブロックを使用しています。

<ItemsControl ItemsSource="{Binding Path=AccountViews.Tables[0]}"
              VirtualizingStackPanel.IsVirtualizing="True">
<ItemsControl.ItemTemplate>
    <DataTemplate>
        <TextBlock Initialized="TextBlock_Initialized"  
                   Margin="5,50,5,50" Text="{Binding Path=Name}" />
    </DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

を変更すると ItemsControlListBox に変更することができます。 Initialized イベントはほんの数回しか実行されませんが (大きな余白は数個のレコードを通過させるためです)、 しかし ItemsControl として、すべての項目が初期化されます。

を設定することを試みました。 ItemsControlPanelTemplateVirtualizingStackPanel に変更する必要がありますが、それでは解決しないようです。

どのように解決するのですか?

実は、単に ItemsPanelTemplate を使う VirtualizingStackPanel . デフォルトの ControlTemplate に対して ItemsControl には ScrollViewer という、仮想化のキーとなる部分がありません。のデフォルトのコントロール・テンプレートに追加すると ItemsControl (のコントロール・テンプレートを使って)。 ListBox をテンプレートとして使用)は、以下のようになります。

<ItemsControl ItemsSource="{Binding AccountViews.Tables[0]}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <TextBlock Initialized="TextBlock_Initialized"
                 Text="{Binding Name}" />
    </DataTemplate>
  </ItemsControl.ItemTemplate>

  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <VirtualizingStackPanel IsVirtualizing="True"
                              VirtualizationMode="Recycling" />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>

  <ItemsControl.Template>
    <ControlTemplate TargetType="ItemsControl">
      <Border BorderThickness="{TemplateBinding BorderThickness}"
              BorderBrush="{TemplateBinding BorderBrush}"
              Background="{TemplateBinding Background}">
        <ScrollViewer CanContentScroll="True" 
                      Padding="{TemplateBinding Padding}"
                      Focusable="False">
          <ItemsPresenter />
        </ScrollViewer>
      </Border>
    </ControlTemplate>
  </ItemsControl.Template>
</ItemsControl>

(ちなみに、デフォルトのコントロール・テンプレートを見るための素晴らしいツールは テンプレートを見る )

注意すること

を設定する必要があります。 ScrollViewer.CanContentScroll="True" を設定する必要があります。 ここで を参照してください。

また、私が VirtualizingStackPanel.VirtualizationMode="Recycling" . これによって TextBlock_Initialized が呼び出される回数を、画面上に表示されている TextBlock の数だけ減らすことができます。UI の仮想化について詳しくは はこちら .

EDIT: 当然のことを言うのを忘れていました: 別の解決法として、単に ItemsControlListBox :) また、これをチェックアウトして MSDN のパフォーマンスの最適化に関するページ を見て、次のことに注目してください。 ItemsControl が "Controls That Implement Performance Features" テーブルにないことに注意してください。