Wednesday, January 16, 2013

WPF ScrollViewer Control Style

How to style a WPF ScrollViewer control?

The ScrollViewer is a control use as a container with auto adjustable content (whenever the content overlaps its parent Height or Width). So, this mean designing of this control is pretty easy since you are not going to place any content inside it. All you have to do is to design the ScrollBars and bind the content.


The ScrollViewer on above image is the parent container that contains the children in color Red. Notice that the ScrollBar both Horizontal and Vertical were displayed. This means that the size of the content of the ScrollViewer overlaps its Height and Width. It gives the user an option to drag the ScrollBar to see the remaining items from the top to bottom, or left to right.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style x:Key="styleScrollViewer" TargetType="{x:Type ScrollViewer}">
        <Setter Property="OverridesDefaultStyle" Value="True"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ScrollViewer}">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <ScrollContentPresenter Grid.Column="0" Grid.Row="0" />
                        <ScrollBar Name="PART_VerticalScrollBar"
                                   Grid.Column="1"
                                   Maximum="{TemplateBinding ScrollableHeight}"
                                   Orientation="Vertical"
                                   Value="{TemplateBinding VerticalOffset}"
                                   ViewportSize="{TemplateBinding ViewportHeight}"
                                   Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" />
                        <ScrollBar Name="PART_HorizontalScrollBar"
                                   Grid.Row="1"
                                   Grid.Column="0"
                                   Maximum="{TemplateBinding ScrollableWidth}"
                                   Orientation="Horizontal"
                                   Value="{TemplateBinding HorizontalOffset}"
                                   ViewportSize="{TemplateBinding ViewportWidth}"
                                   Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>

                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

You will notice two PARTS. One is PART_VerticalScrollBar that holds the ScrollBar for VerticalOffset and one is PART_HorizontalScrollBar that holds the ScrollBar for HorizontalOffset.

Also, there is an ScrollContentPresenter object placed inside the template. This object is used by ScrollViewer where to display the content.

Most of the design for ScrollViewer is to change the Style of the ScrollBar. In this blog, I have to show how I manage to integrate the stuffs I made in the WPF ScrollBar Style.

First, we have to reference the XAML file of the ScrollBar to our ResourceDictionary. Below is the way how to do it.

<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="ScrollBar.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>

After we have referenced the ScrollBar.xaml file, apply the Style in the ScrollBar object inside the ScrollViewer template. To do this, please see the XAML below in yellow background.

<ScrollBar Name="PART_VerticalScrollBar"
            Grid.Column="1"
            Maximum="{TemplateBinding ScrollableHeight}"
            Orientation="Vertical"
            Style="{DynamicResource ResourceKey=styleScrollBar}"
            Value="{TemplateBinding VerticalOffset}"
            ViewportSize="{TemplateBinding ViewportHeight}"
            Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" />
<ScrollBar Name="PART_HorizontalScrollBar"
            Grid.Row="1"
            Grid.Column="0"
            Maximum="{TemplateBinding ScrollableWidth}"
            Orientation="Horizontal"
            Style="{DynamicResource ResourceKey=styleScrollBar}"
            Value="{TemplateBinding HorizontalOffset}"
            ViewportSize="{TemplateBinding ViewportWidth}"
            Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>

The result is below.


You will see that the ScrollBar style has been applied on our ScrollViewer.

Applying Style in ScrollViewer

Same as what I had done with any other Style. You have to compile all the XAML codes in one ResourceDictionary file and place it anywhere in your Solution. Set the Build Action to Resource and add a reference by placing it inside MergeDictionaries property of your Window.Resources (or parent FrameworkElement.Resources) property. The XAML codes below is the sample.

<Window x:Class="CodesDirectory.WIN_ScrollViewer"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="WPF ScrollViewer" SizeToContent="WidthAndHeight">
    <Window.Resources>
        <ResourceDictionary Source="/Styles/ScrollViewer.xaml"></ResourceDictionary>
    </Window.Resources>
    <Grid>
        <ScrollViewer Background="#F7F7F7"
                      BorderBrush="#C7C7C7"
                      Height="300"
                      HorizontalScrollBarVisibility="Auto"
                      Margin="10"
                      Style="{DynamicResource ResourceKey=styleScrollViewer}"
                      VerticalScrollBarVisibility="Auto"
                      Width="400">
            <StackPanel Background="Red" Height="400" Width="500"></StackPanel>
        </ScrollViewer>
    </Grid>
</Window>

And that's it. You just finish the article of how to design the ScrollViewer.

2 comments:

Place your comments and ideas