简体   繁体   中英

uwp - scrollviewer doesn't keep scroll position when content is updated

I have this following XAML for my ScrollViewer

<!-- Scroller -->
<ScrollViewer x:Name="Scroller"
              Margin="0 75 0 0"
              Width="1080"
              Height="560"
              HorizontalScrollMode="Enabled"
              HorizontalScrollBarVisibility="Auto" 
              HorizontalSnapPointsType="MandatorySingle"
              HorizontalSnapPointsAlignment="Center">

   <StackPanel x:Name="StackItems"
               Orientation="Horizontal"
               Background="Transparent"
               HorizontalAlignment="Center"
               Width="Auto"
               Padding="920 0 0 0">
   </StackPanel>
</ScrollViewer>

The problem is when I use method Insert of StackPanel to add a new item, the new item push the current view to either left or right according to the index I add. For example: There are 5 items in my StackPanel now, and I scrolled to the last index (4th), then while I am viewing index 4th and I added new Item to the first as shown below, my current view will be pushed to item 3rd and I need to scroll right once to get the 4th Item again.

this.StackItems.Children.Insert(0, new Item());

For this following matter, Could anyone tell me how to keep the current viewport active even if there is new item is added to the StackPanel ? Appreciate that. Thank you!

There are two ways I can think of right away that use the ScrollViewer .

All methods below assume you know the index of the item you want to bring into view. If you don't know this you can use the current scrolllocation or selected item (in case of a ListView ) to obtain this index.

The first method is by using ScrollViewer.ChangeView() :

After you have added a new item to StackItems you can add this line of code:

Scroller.ChangeView(
    StackItems.Padding.Left + 
        StackItems.Children
                  .Take(indexToBringIntoView)
                  .Sum(u => u.ActualSize.X),
    null,
    null
);

If the width of all items are equal you can instead just write of course:

Scroller.ChangeView(StackItems.Padding.Left + itemWidth * indexToBringIntoView, null, null);

The second method is by using UIElement.StartBringIntoView() :

This method is easier than the first method, however I have noticed some strange behaviour of the ScrollViewer when using this.

After adding your new item to the StackItems you can use the following the bring you previous item into view:

StackItems.Children[indexToBringIntoView].StartBringIntoView();

Another way of achieving your goal is to use a horizontal ListView

You can set this up following the accepted answer from this SO thread.

Then if you have the index of the item you want to bring into view you can use ListView.ScrollIntoView(object item) like so:

listView.ScrollIntoView(Lister.Items[indexToBringIntoView]);

I have included this method as well since this is a very solid working method and I never had a problem with it.


If this is not what you are looking for, let me know and I'll adjust my answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM