Accurate scrollbar control in an ItemsControl with a VirtualizingStackPanel

被刻印的时光 ゝ 提交于 2019-12-25 08:58:37

问题


I have an Itemscontrol using a VirtualizingStackPanel to display a huge (and growing) list of items:

<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>

The virtualization is working like a charm, but i cannot get the management of the scrollbar right. If I try to programmatically (e.g. on load) scroll to the bottom like i do in non-virtualized StackPanels:

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

the scrollviewer tries to scroll to the bottom, but does not do so completely - it always stops a bit before the "real" bottom. This makes sense in a way since VirtualizingStackPanels are using the scroll value to determine which items to render, but it is totally grinding my gears and unacceptable for end users.

How can I scroll to the "real" bottom? What do I have to do if i want to scroll exactly so far down that the top of a certain item is at the top of the viewport (unless the "real" bottom is too close, naturally)?


回答1:


This is because the built-in ItemsControl class doesn't support virtualization. You can try a ListBox instead, which uses UI virtualization by default.

If you don't want to have selection behaviour, just set:

<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>

and then something like:

 lbCustom.ScrollIntoView(lbCustom.Items[lbCustom.Items.Count - 1]


来源:https://stackoverflow.com/questions/45886640/accurate-scrollbar-control-in-an-itemscontrol-with-a-virtualizingstackpanel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!