views:

1797

answers:

1

I have a Scrollviewer inside a TabControl, and for some reason when you change tabs my ScrollViewer jumps to HorizontalOffset of 12. My ScrollViewer, among other things has a ListView inside it with an unrestricted height. It's a strange layout, but everything inside the scroller had to be printable so I couldn't easily allow the ListView to scroll on its own.

So I tried the following lines in the SelectionChanged event of the TabControl:

Console.WriteLine(Scroller.HorizontalOffset);
Scroller.ScrollToHorizontalOffset(0);
Console.WriteLine(Scroller.HorizontalOffset);

And they print out 12 for both calls to WriteLine()... It also does not move, but you can scroll from the actual UI.

Does anyone know what would cause this strange behavior?

I will try to find suitable code to post, but it's a large project and might be difficult to recreate in a sample solution.

Other info:

  • The issue only happens if the content is large enough where it can horizontally scroll.
  • My horizontal and vertical scrollbar visibility is Auto, but the issue still happens if they are set to Hidden or Visible.

UPDATE:

If you click my ListView that's inside the ScrollViewer and select an item, the ScrollViewer scrolls to this same 12 pixel offset. Could my issue be related to my ListView getting focus? Does a ListView call BringIntoView() on itself when it receives focus?

This Xaml reproduces the issue:

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window11" Height="300" Width="300">
<TabControl>
    <TabItem Header="Tab One">
     <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
      <ListBox Margin="25,0,0,0" Width="2000">
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>   
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      </ListBox>
     </ScrollViewer>
    </TabItem>
    <TabItem Header="Tab Two">
     <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
      <ListBox Margin="25,0,0,0" Width="2000">
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>   
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      <ListBoxItem>WOOT WOOT WOOT WOOT</ListBoxItem>
      </ListBox>
     </ScrollViewer>
    </TabItem>
</TabControl>
</Window>

Slap this in XamlPad, run it. Click a Tab header and notice the ScrollViewer scroll on its own, play around with it and notice how my margin on the ListBox is scrolled off screen. How do I prevent or workaround this behavior? It makes my layout look pretty janky in my case.

+1  A: 

Looks like you have to hook into RequestBringIntoView:

private void ListView_RequestBringIntoView(object sender, RequestBringIntoViewEventArgs e)
{
    e.Handled = true;
}

Seems like a pretty simple solution.

Jonathan.Peppers