Virtualisieren ein Item?
-
03-10-2019 - |
Frage
Ich habe eine ItemsControl
eine Liste von Daten enthalten, dass ich möchte, virtualisieren jedoch VirtualizingStackPanel.IsVirtualizing="True"
scheint nicht mit einem ItemsControl
zu arbeiten.
Ist das wirklich der Fall ist, oder gibt es eine andere Art und Weise, dies zu tun, dass ich bin mir nicht bewusst?
Um zu testen, habe ich den folgenden Code-Block wurde mit:
<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>
Wenn ich die ItemsControl
zu einem ListBox
ändern, kann ich sehen, dass das Initialized
Ereignis läuft nur ein paar Mal (die großen Margen sind nur so habe ich nur durch ein paar Aufzeichnungen gehen), aber als ItemsControl
jedes Element bekommt initialisiert.
Ich habe versucht, die ItemsControlPanelTemplate
auf einen VirtualizingStackPanel
Einstellung, aber das scheint nicht zu helfen.
Lösung
Es gibt tatsächlich viel mehr zu bieten, als nur die ItemsPanelTemplate
Verwendung VirtualizingStackPanel
. Der Standard ControlTemplate
für ItemsControl
hat keine ScrollViewer
, die der Schlüssel zur Virtualisierung ist. Zusätzlich zu der der Standard-Steuerelementvorlage für ItemsControl
(unter Verwendung der Steuervorlage für ListBox
als Vorlage) gibt uns die folgenden:
<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>
(BTW, ein großes Werkzeug für das Betrachten Standard-Steuerungsschablonen ist zeigen mir die Vorlage )
Reise Hinweis:
Sie müssen Set ScrollViewer.CanContentScroll="True"
finden Sie unter hier warum.
Beachten Sie auch, dass ich legte VirtualizingStackPanel.VirtualizationMode="Recycling"
. Dies wird die Zahl der Zeiten TextBlock_Initialized
reduzieren wird aufgerufen jedoch viele Textblocks auf dem Bildschirm sichtbar sind. Sie können mehr über UI-Virtualisierung lesen Sie hier
.
EDIT: Vergessen, das Offensichtliche zu sagen: als eine alternative Lösung, können Sie einfach ItemsControl
mit ListBox
ersetzen :)
Außerdem lesen Sie in dieser Optimierung der Leistung auf MSDN-Seite und bemerke, dass ItemsControl
nicht in der ist „Controls das Implementieren Leistungsmerkmale“ Tabelle, weshalb wir bearbeiten müssen die Steuervorlage.
Andere Tipps
Aufbauend auf DavidN Antwort, hier ist ein Stil, den Sie auf einem Itemscontrol verwenden kann es virtualisieren:
<!--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>
Ich weiß nicht, wie der Vorschlag, eine List-Box verwenden, da sie die Auswahl von Zeilen ermöglichen, wo Sie müssen nicht es wollen.
Es ist nur, dass der Standard ItemsPanel
kein VirtualizingStackPanel
ist. Sie müssen es ändern:
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>