アイテムコントロールを仮想化しますか?
-
03-10-2019 - |
質問
を持っています 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>
変更した場合 ItemsControl
に ListBox
, 、私はそれを見ることができます Initialized
イベントはほんの一握りの回数しか実行されません(巨大なマージンはちょうどあるので、私はいくつかのレコードを実行する必要があります)。 ItemsControl
すべてのアイテムが初期化されます。
設定しようとしました ItemsControlPanelTemplate
に VirtualizingStackPanel
しかし、それは助けにはならないようです。
解決
実際には、単に作る以上のものがあります ItemsPanelTemplate
使用する VirtualizingStackPanel
. 。デフォルト ControlTemplate
にとって ItemsControl
持っていない ScrollViewer
, 、これが仮想化の鍵です。デフォルトのコントロールテンプレートに追加 ItemsControl
(のコントロールテンプレートを使用します ListBox
テンプレートとして)は以下を提供します。
<ItemsControl
VirtualizingStackPanel.IsVirtualizing="True"
ScrollViewer.CanContentScroll="True"
ItemsSource="{Binding Path=AccountViews.Tables[0]}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock
Initialized="TextBlock_Initialized"
Text="{Binding Path=Name}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Template>
<ControlTemplate>
<Border
BorderThickness="{TemplateBinding Border.BorderThickness}"
Padding="{TemplateBinding Control.Padding}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}"
SnapsToDevicePixels="True">
<ScrollViewer
Padding="{TemplateBinding Control.Padding}"
Focusable="False">
<ItemsPresenter
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
(ところで、デフォルトのコントロールテンプレートを調べるための優れたツールは テンプレートを見せてください)
注意すべきこと:
設定する必要があります ScrollViewer.CanContentScroll="True"
, 、 見る ここ なぜ。
また、私が置くことに注意してください VirtualizingStackPanel.VirtualizationMode="Recycling"
. 。これにより、回数が減ります TextBlock_Initialized
ただし、画面上に多くのテキストブロックが表示されています。 UI Virtualizationの詳細をお読みください ここ.
編集:明白を述べるのを忘れました:代替ソリューションとして、あなたはただ交換することができます ItemsControl
と ListBox
:)また、これをチェックしてください MSDNページでパフォーマンスを最適化します そしてそれに注意してください ItemsControl
「パフォーマンス機能を実装するコントロール」テーブルには含まれていないため、コントロールテンプレートを編集する必要があります。
他のヒント
Davidnの答えに基づいて、ここにあなたがそれを仮想化するためにitemsControlで使用できるスタイルがあります:
<!--Virtualised ItemsControl-->
<Style x:Key="ItemsControlVirtualizedStyle" TargetType="ItemsControl">
<Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ItemsControl">
<Border
BorderThickness="{TemplateBinding Border.BorderThickness}"
Padding="{TemplateBinding Control.Padding}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}"
SnapsToDevicePixels="True"
>
<ScrollViewer Padding="{TemplateBinding Control.Padding}" Focusable="False">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
必ずしもそれを望んでいない行の選択を許可するため、リストボックスを使用するという提案が好きではありません。
デフォルトだけです ItemsPanel
ではありません VirtualizingStackPanel
. 。あなたはそれを変更する必要があります:
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>