In the
last post we took the simple
ScrollViewer thumbnail and
controllerized it. This time, we're going to make it interactive.
And, because WPF totally rocks, it's stupidly easy to do.
Normally, we'd do lots of mouse capture, remember the original location and the new location to calculate the delta etc etc. With WPF, we can simply use the
Thumb control that fires a DragDelta event if the user makes a drag gesture over the control. Huzzah.
So, we need to quickly change the ScrollViewerThumbnail's template in Generic.xaml to look like this:
<ControlTemplate TargetType="{x:Type Controls:ScrollViewerThumbnail}">
<Viewbox DataContext="{TemplateBinding ScrollViewer}" Stretch="Uniform">
<Grid>
<Rectangle
Width="{Binding Content.ActualWidth}"
Height="{Binding Content.ActualHeight}">
<Rectangle.Fill>
<VisualBrush Visual="{Binding Content}" />
</Rectangle.Fill>
</Rectangle>
<Thumb Name="PART_Highlight"
Background="{TemplateBinding HighlightFill}"
Width="{Binding ViewportWidth}"
Height="{Binding ViewportHeight}"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<Thumb.RenderTransform>
<TranslateTransform
X="{Binding HorizontalOffset}"
Y="{Binding VerticalOffset}" />
</Thumb.RenderTransform>
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Border Background="{TemplateBinding Background}" />
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Grid>
</Viewbox>
</ControlTemplate>
Note that we've changed the highlight from a Border to a Thumb. We've named it PART_Highlight and I've given the thumb a ControlTemplate that is a simple Border (Thumbs can't have content).
Next, we need to find the PART_Highlight in our ScrollViewerThumbnail template and attach a handler to it's DragDelta event. We can't just use this.FindName("PART_Highlight") because it's part of a template. We have to override the OnApplyTemplate method of the ScrollViewerThumbnail class and use this.Template.FindName("PART_Highlight"):
private const string PART_Highlight = "PART_Highlight";
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var partHighlight = (Thumb)this.Template.FindName(PART_Highlight, this);
partHighlight.DragDelta += partHighlight_DragDelta;
}
Next, we need to move the ScrollViewer when the DragDelta event occurs.
void partHighlight_DragDelta(object sender, DragDeltaEventArgs e)
{
ScrollViewer.ScrollToVerticalOffset(ScrollViewer.VerticalOffset + e.VerticalChange);
ScrollViewer.ScrollToHorizontalOffset(ScrollViewer.HorizontalOffset + e.HorizontalChange);
}
And we're done. Seriously! I'm blown away that this can be achieved with just four-ish lines of code.
I've uploaded an example (ClickOnce deployed that you can play with).... get it here:
>>> Download ClickOnce Demo <<<

Just click on the Arrows icon to display a popup showing the ScrollViewer thumbnail.
PS - you can use the mouse wheel to change the size of the ScrollViewerThumbnail control too.

Post By
Josh Twist
11:56 AM
04 Dec 2008
» Next Post:
My new favourite Resharper features
« Previous Post:
Controllerizing the ScrollViewer Thumbnail
Comments are closed for this post.
Posted by
Markenzie
@
21 Dec 2008
3:25 PM
I have got "WPF ScrollViewer Thumbnail" and "Controllerizing the ScrollViewer Thumbnail" to work fine for me. But I am NOT getting this ("Making the ScrollViewerThumbnail interactive") to work. First I got this error "All objects added to an IDictionary must have a Key attribute or some other type of key associated with them" with the Generic.xaml file and I inserted a x:Key="xxx" and that removed the error.
The program runs without error but I cannot get the thumbnail to show as in the previous 2 posts. Only the scrollviewer shows. Please help OR you can also send me the code of the Clickonce demo here.
Thanks a lot for this post.
Posted by
Josh Twist
@
22 Dec 2008
5:06 AM
Hi Markenzie,
Does this help?
http://www.thejoyofcode.com/Reflectorizing_a_ClickOnce_app.aspxI'm happy to post the code if not.
Josh
Posted by
Markenzie
@
25 Dec 2008
8:23 AM
Thanks a lot Josh. I got it to work. Your post
"Reflectorizing a ClickOnce app" was very, very helpful. Thanks a million and Happy Christmas
/Markenzie
Posted by
Dennis
@
10 Nov 2011
12:04 PM
Hi Josh, thank you for sharing this great and smart control. The ClickOnce demo doesn't work. It reports "Application cannot be started.". Is it possible for you to post the code? Thanks in advance.
Posted by
Josh
@
10 Nov 2011
5:45 PM
Hi Dennis,
Do you have .NET installed - I just stried it on a virgin machine and it worked fine. Also, there is a link above that shows how to tear apart a clickonce app - I'm afriad I don't have the code any longer :(.
Josh