Виртуализация 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 к a ListBox, Я вижу что Initialized событие только работает несколько разы (огромные поля именно так, я только должен пройти несколько записей), однако как ItemsControl каждый объект инициализируется.

Я попытался установить ItemsControlPanelTemplate к a VirtualizingStackPanel но это, кажется, не помогает.

121
задан Rachel 19 March 2012 в 14:20
поделиться

2 ответа

На самом деле это гораздо больше, чем просто создание 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 , сколько бы текстовых блоков ни отображалось на экране. Подробнее о виртуализации пользовательского интерфейса можно прочитать здесь .

РЕДАКТИРОВАТЬ: Забыл указать очевидное: в качестве альтернативного решения вы можете просто заменить ItemsControl на ListBox :) Также ознакомьтесь с этим Оптимизация производительности на странице MSDN и обратите внимание, что ItemsControl нет в таблице «Элементы управления, реализующие функции производительности», поэтому нам нужно отредактировать шаблон элемента управления.

210
ответ дан 24 November 2019 в 01:31
поделиться

Просто по умолчанию ItemsPanel не является VirtualizingStackPanel. Вам нужно изменить его:

<ItemsControl>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>
-3
ответ дан 24 November 2019 в 01:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: