Точное управление полосой прокрутки в ItemsControl с VirtualizingStackPanel

У меня есть Itemscontrol, использующий VirtualizingStackPanel для отображения огромного (и растущего) списка элементов:

<ItemsControl Grid.Row="1" Name="ConversationItemsControl" VirtualizingStackPanel.VirtualizationMode="Recycling">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel Orientation="Vertical" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.Template>
        <ControlTemplate TargetType="ItemsControl">
            <ScrollViewer>
                <ItemsPresenter />
            </ScrollViewer>
        </ControlTemplate>
    </ItemsControl.Template>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <local:Message />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Виртуализация работает как шарм, но я не могу правильно управлять полосой прокрутки. Если я пытаюсь программно (например, при загрузке) прокрутить до конца, как я делаю в не виртуализированных StackPanels:

var scrollViewer = VisualTreeHelper.GetChild(ConversationItemsControl, 0) as ScrollViewer;
scrollViewer.ChangeView(null, double.MaxValue, 1f, true);

scrollviewer пытается прокрутить до самого дна, но не делает этого полностью - он всегда немного останавливается перед "настоящим" дном. В некотором смысле это имеет смысл, поскольку VirtualizingStackPanels использует значение прокрутки, чтобы определить, какие элементы следует визуализировать, но это совершенно не подходит для конечных пользователей.

Как прокрутить до "настоящего" дна? Что мне нужно сделать, если я хочу прокрутить ровно так вниз, чтобы верх определенного элемента находился в верхней части области просмотра (если, конечно, "реальное" дно не слишком близко)?

1 ответ

Решение

Это потому, что встроенный класс ItemsControl не поддерживает виртуализацию. Вместо этого вы можете попробовать ListBox, который по умолчанию использует виртуализацию пользовательского интерфейса.

Если вы не хотите иметь поведение выбора, просто установите:

<ListBox x:Name="lbCustom">
        <ListBox.ItemContainerStyle>
            <Style TargetType="ListBoxItem">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListBoxItem">
                            <ContentPresenter/>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListBox.ItemContainerStyle>
    </ListBox>

а потом что-то вроде:

 lbCustom.ScrollIntoView(lbCustom.Items[lbCustom.Items.Count - 1]
Другие вопросы по тегам