Wirtualizacja ItemsControl?
Mam ItemsControl
zawierający listę danych, które chciałbym zwirtualizować, jednak VirtualizingStackPanel.IsVirtualizing="True"
nie wydaje się działać z ItemsControl
.
Czy tak naprawdę jest, czy jest inny sposób na zrobienie tego, o czym Nie wiem?
Do testowania używam poniższego bloku kodu:
<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>
Jeśli zmienię {[1] } na ListBox
, widzę, że zdarzenie Initialized
działa tylko kilka razy( ogromne marginesy są po prostu więc muszę przejść przez kilka rekordów), jednak jako {[1] } każdy element zostaje zainicjalizowany.
Próbowałem ustawić ItemsControlPanelTemplate
na VirtualizingStackPanel
, ale to chyba nie pomaga.
3 answers
W rzeczywistości jest o wiele więcej niż tylko użycie ItemsPanelTemplate
VirtualizingStackPanel
. Domyślnie ControlTemplate
dla ItemsControl
nie ma ScrollViewer
, który jest kluczem do wirtualizacji. Dodanie do domyślnego szablonu kontrolnego dla ItemsControl
(używając szablonu kontrolnego dla ListBox
jako szablonu) daje nam następujące:
<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, świetnym narzędziem do przeglądania domyślnych szablonów sterowania jest Show Me the Template )
Rzeczy do zauważenia:
Musisz ustawić ScrollViewer.CanContentScroll="True"
, Zobacz tutaj Po co.
Zauważ również, że ja umieściłem VirtualizingStackPanel.VirtualizationMode="Recycling"
. Zmniejszy to liczbę wywołań TextBlock_Initialized
do tego, ile blokad tekstowych jest widocznych na ekranie. Więcej informacji na temat wirtualizacji interfejsu znajdziesz tutaj
.
EDIT: zapomniałem podać oczywiste: jako alternatywne rozwiązanie możesz zastąpić ItemsControl
przez ListBox
:)
Sprawdź również ten Optymalizacja wydajności na stronie MSDN i zauważ, że ItemsControl
nie znajduje się w " kontrolkach implementujących wydajność Tabele funkcji", dlatego musimy edytować szablon kontrolki.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-17 08:27:38
Bazując na odpowiedzi Davidna, oto styl, którego możesz użyć na ItemsControl, aby go wirtualizować:
<!--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>
Nie podoba mi się sugestia użycia Listboxa, ponieważ pozwalają one na wybór wierszy, w których niekoniecznie chcesz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-27 15:11:35
Po prostu domyślne ItemsPanel
nie jest VirtualizingStackPanel
. Musisz to zmienić:
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-06 20:15:16