As I got to know WPF, one of the features that I really like was the ability to bind the value of one control to the value of another one. Well, the other day I had a situation where I had 2 ScrollViewers side by side and I wanted to the two of them to be in sync. So, if I used the scrollbar one the left one I'd like the one on the right to scroll by the same increment. My first thought was then to bind the value of the offset of the scrollbars, that would be simple right? Not. The offset property is readonly. The way around this is really simple, you need you use the ScrollChanged event and in that event you use the method ScrollToVerticalOffset to move the ScrollBar of the other ScrollViewer.
Here is an example where I have a window with two ScrollViewers, each one has a ListBox with 7 items inside. As you scroll on the left side scroll viewer to see all the items in the ListBox you will notice that the ScrollViewer on the right will follow.
<Window x:Class="WpfScrollbarSync.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="100" Width="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<ScrollViewer Grid.Column="0" Name="scrollViewerLeft" ScrollChanged="scrollViewerLeft_ScrollChanged">
<ListBox>
<ListBoxItem>1</ListBoxItem>
<ListBoxItem>2</ListBoxItem>
<ListBoxItem>3</ListBoxItem>
<ListBoxItem>4</ListBoxItem>
<ListBoxItem>5</ListBoxItem>
<ListBoxItem>6</ListBoxItem>
<ListBoxItem>7</ListBoxItem>
</ListBox>
</ScrollViewer>
<ScrollViewer Grid.Column="1" Name="scrollViewerRight">
<ListBox>
<ListBoxItem>1</ListBoxItem>
<ListBoxItem>2</ListBoxItem>
<ListBoxItem>3</ListBoxItem>
<ListBoxItem>4</ListBoxItem>
<ListBoxItem>5</ListBoxItem>
<ListBoxItem>6</ListBoxItem>
<ListBoxItem>7</ListBoxItem>
</ListBox>
</ScrollViewer>
</Grid>
</Window>
And here is the codebehind:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void scrollViewerLeft_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
scrollViewerRight.ScrollToVerticalOffset((sender as ScrollViewer).VerticalOffset);
}
}
I hope this can save someone one minute or two. :-)