Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Synchronize Two Scroll Viewers in WPF

0.00/5 (No votes)
20 Mar 2013 1  
Often we try to synchronize scrolling, but WPF does not have a direct support for this one. Therefore, this article is on that.

Introduction

First of all, I must stress upon that I am no author and this is my first article ever. I am not even sure whether I would continue to write. I am solely writing this so that, it would prevent someone else going through the hassle of what I went through to discover this solution.  Most probably, I would not have time to improve or do bug fixes, if any.

Secondly, this is not my code/thought. I just merely updated it so, that it would provide more flexibility.

The original owner of this code is CodeProject user Karin Huber and all I did was improving her code from the article "Scroll Synchronization". 

Background  

As you can see from the above screenshot (I was lazy to make a comprehensive UI), consider a scenario where you have to synchronize two scroll bars (i.e., one would be automatically scrolled, when the other is scrolled). In conventional windows programming we would capture the offset in the code behind and we write the logic. But as we move into WPF, we are introduced to MVVM architecture (I won't be dwelling on this very much) where data binding is everything and code behinds are evil Big Grin | <img src= 

But sadly, scroll viewers cannot be bound as such, owing to the fact that the developer who developed this control did not implement the required properties as 'DependencyProperty'.

So in the above mentioned article, this scenario is addressed and solved very elegantly. The only bottleneck was that, he synchronized both scroll bars. I wanted them to be bound separately/independent, which is what I have achieved in this attempt. 

Using the code

This article will not describe the solution in detail. So please, read the above referenced article.

I would not go into detail about DependencyProperty objects in C#, but for the record, this entire solution is based on Dependency Properties. So, if you do not know about it, please read about them. There are many valuable CP articles on that topic. 

Also, I won't go into much technical details as Karin's article covers pretty much all the details. I'd explain how to use my code.

The solution is implemented in the ScrollSynchronizer and to there are three DependencyProperty implemented like this:

public static readonly DependencyProperty HorizontalScrollGroupProperty = 
  DependencyProperty.RegisterAttached(HorizontalScrollGroupPropertyName, typeof(string), 
  typeof(ScrollSynchronizer), new PropertyMetadata(string.Empty, OnHorizontalScrollGroupChanged));

public static readonly DependencyProperty VerticalScrollGroupProperty =	
  DependencyProperty.RegisterAttached(VerticalScrollGroupPropertyName, typeof(string), 
  typeof(ScrollSynchronizer), new PropertyMetadata(string.Empty, OnVerticalScrollGroupChanged));

public static readonly DependencyProperty ScrollSyncTypeProperty = 
  DependencyProperty.RegisterAttached(ScrollSyncTypePropertyName, typeof(ScrollSyncType), 
  typeof(ScrollSynchronizer), new PropertyMetadata(ScrollSyncType.None, OnScrollSyncTypeChanged));

To use these properties, refer as below in your XAML:

xmlns:Core="clr-namespace:ScrollViewerSynchronization.Core"

After that, you can use them like:

<ScrollViewer Grid.Row="0" Grid.Column="0" HorizontalScrollBarVisibility="Visible" 
  Core:ScrollSynchronizer.VerticalScrollGroup="V1" Core:ScrollSynchronizer.HorizontalScrollGroup="H1"> 

As you may have noticed, these properties inject themselves into ScrollViewer type in XAML. Assuming, now you know how to use the code, I'll explain how to use these properties.

Important thing is, none of the properties are dependent on each other. I.e. you can use these individually or as a combination as preferred.

  • VerticalScrollGroup:  The data type of the property is string. All scrollviewers having the same value for this property is vertically scrolled together. Default value: string.Empty
  • HorizontalScrollGroup: The data type of the property is string. All scrollviewers having the same value for this property is horizontally scrolled together. Default value: string.Empty 
  • ScrollSyncType: The data type of the property is ScrollSyncType enum which is defined within the class. There are four possible values:
    • None: Default value of this property. Scrolling will be disabled.
    • Horizontal: Scrolling synced only horizontal.
    • Vertical: Scrolling synced only vertical.
    • Both: Scrolling synced both vertical and horizontal.

If you set VerticalScrollGroup without setting ScrollSyncType, it will automatically be assigned to ScrollSyncType.Vertical. If the ScrollSyncType was set to ScrollSyncType.Horizontal, it would be updated to ScrollSyncType.Both. This logic applies to HorizontalScrollGroup as well.

If you set ScrollSyncType without setting VerticalScrollGroup or HorizontalScrollGroup, the synchronizing will be done accordingly assuming that the VerticalScrollGroup = string.Empty and HorizontalScrollGroup = string.Empty 

Points of Interest 

Once again special thanks to Kavin Huber for that wonderful article which pointed me in this way. I discovered a new way of thinking to push the boundaries/limitations of WPF XAML. I hope someone would be benefited out of this article.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here