Вопрос

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

Редактировать: забыл указать очевидное: как альтернативное решение, вы можете просто заменить ItemsControl с участием ListBox :) Кроме того, проверить это Оптимизация производительности на странице MSDN и обратите внимание на это ItemsControl Не находится в таблице «Управления, которые реализуют функции производительности», поэтому нам нужно редактировать шаблон управления.

Другие советы

Строительство на ответе Давидна, вот стиль, который вы можете использовать на элементахControl для виртуализации его:

<!--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>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top