Виртуализация ItemsControl?
у меня есть 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 но это, кажется, не помогает.
3 ответов:
на самом деле гораздо больше, чем просто
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вызывается, однако многие текстовые блоки видны на экране. Вы можете прочитать больше о виртуализации пользовательского интерфейса здесь .EDIT: забыл указать очевидное: в качестве альтернативного решения вы можете просто заменить
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>мне не нравится предложение использовать ListBox, поскольку они позволяют выбирать строки, где вы этого не обязательно хотите.
это просто, что по умолчанию
ItemsPanelнеVirtualizingStackPanel. Вам нужно изменить его:<ItemsControl> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <VirtualizingStackPanel /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> </ItemsControl>
Comments