Получение виртуализации пользовательского интерфейса, работающего с ItemsControl в Silverlight

Я пытаюсь создать прокручивающийся список довольно больших текстовых блоков. Я хочу, чтобы была вертикальная полоса прокрутки, чтобы показать их все, и если они превышают определенный размер, я хочу, чтобы они отображали многоточие. У меня на самом деле все это работает довольно хорошо.

У меня есть следующий Silverlight XAML:

<Grid x:Name="LayoutRoot" MaxWidth="500" MinWidth="100"
    MaxHeight="500" MinHeight="100">
    <Grid.DataContext>
        <app:MainPageViewModel/>
    </Grid.DataContext>
    <ScrollViewer>
    <ItemsControl ItemsSource="{Binding TextItems}" Margin="0,20,0,20">
        <ItemsControl.ItemTemplate><DataTemplate>
            <Border MaxHeight="175" Margin="0,0,0,18" CornerRadius="5">
                <TextBlock Margin="2" TextTrimming="WordEllipsis"
                     TextWrapping="Wrap" Text="{Binding}"/>
            </Border>
         </DataTemplate></ItemsControl.ItemTemplate>
    </ItemsControl>
    </ScrollViewer>
</Grid>

Моя проблема заключается в том, что этот макет не использует виртуализацию пользовательского интерфейса, например, с VirtualizingStackPanel. Так что это довольно медленно. Каков наилучший способ включить виртуализацию пользовательского интерфейса в этот макет? Я пробовал около полудюжины разных способов, и ничего не получилось.

Мне удалось заставить это работать в ListBox, потому что он, кажется, поддерживает виртуализацию из коробки. Тем не менее, я бы предпочел использовать ItemsControl, так как я не хочу, чтобы эти вещи выбирались, и я не хочу, чтобы стиль, который поставляется вместе с ListBox.

Это в Silverlight 4.

1 ответ

Решение

Есть несколько вещей, которые вам нужно сделать, чтобы сделать эту работу.

  1. Установите для ItemsPanelTemplate для ItemsControl значение VirtualizingStackPanel.
  2. Включите ScrollViewer в ControlTemplate для ItemsControl вместо того, чтобы просто оборачивать его снаружи.
  3. Убедитесь, что ItemsControl имеет фиксированную высоту, чтобы система макетов могла определить, сколько элементов необходимо заполнить область просмотра. (Похоже, вы уже делаете это, помещая ItemsControl в Grid - это позволит системе макетов определить выделенную высоту для элемента управления)

Вот самый простой пример, который я мог бы придумать для этой работы:

    <ItemsControl ItemsSource="{Binding TextItems}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.Template>
            <ControlTemplate TargetType="ItemsControl">
                <Border>
                    <ScrollViewer>
                        <ItemsPresenter/>
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </ItemsControl.Template>
    </ItemsControl>
Другие вопросы по тегам