Click here to Skip to main content
15,867,594 members
Articles / Desktop Programming / WPF

Styling a ScrollViewer/Scrollbar In WPF

Rate me:
Please Sign up or sign in to vote.
4.94/5 (32 votes)
17 Jun 2009CPOL2 min read 359.2K   3.5K   57   33
Styling a ScrollViewer/Scrollbar In WPF

A while ago, I was looking at the Infragistics WPF showcase, Tangerine and I was quite jealous about the scrollbars that they managed to use. I mean styling a Button is one thing, but the ScrollBar is made of lots of nasty different control parts, (Part_XXX elements). Incidentally, I wrote an article about Part_XXX elements in a WPF article over at CodeProject right here if you are interested.

Anyways, to cut a long story short, I decided to try and have a go at Styling a bigger control such as ScrollViewer. And guess what I managed to do it. Hooray!

This is what it looks like:

37366/newstyle.png37366/origstyle.png
My Styled ScrollViewer
Original ScrollViewer

This blog entry outlines the steps I went through.

Step 1

Look up and copy the original ScrollViewer and ScrollBar Templates from MSDN, for example:

Then I pasted that code from MSDN into a Resources file in a WPF window.

Step 2

I examined the control parts required for the full ScrollViewer/Scrollbar controls. This was fairly ok actually as the MSDN default Styles and pretty easy to follow.

From looking at the default styles, it became clear that I needed to look at the following Style/Templates if I wished to re-style a ScrollViewer, as all of these were used in the default Style for the ScrollViewer somewhere.

Step 3

I then decided which parts I want to swap out. I chose to swap out and proceeded to hack the default Style/Templates to achieve the look I was after.

Anyway, the results ScrollViewer looks like the following image:

  • RepeatButton
  • Thumb
  • ScrollBar
  • ScrollViewer

     

When you consider the following image, you can see why these are the Style/Templates that need to be altered.

37366/scroll.png

So basically after that, it's just a question of cutting code. So without further ado, here is the code:

XML
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006″
    x:Class="ScrollViewerTemplate.Window1″
    x:Name="Window"
    Title="Window1″
    Width="200″ Height="200″>

  <Window.Resources>

        <!– All the following is required to Re-Style the ScrollViewer, see 
             http://msdn2.microsoft.com/en-us/library/aa970847(VS.85).aspx
             http://msdn2.microsoft.com/en-us/library/ms742173(VS.85).aspx
             for the default Styles that the ScrollViewer has out of the box
         –>

        <!– Brushes used in Styling of ScrollViewer –>
        <SolidColorBrush x:Key="StandardBorderBrush" Color="#888″ />
        <SolidColorBrush x:Key="StandardBackgroundBrush" Color="#FFF" />
        <SolidColorBrush x:Key="HoverBorderBrush" Color="#DDD" />
        <SolidColorBrush x:Key="SelectedBackgroundBrush" Color="Gray" />
        <SolidColorBrush x:Key="SelectedForegroundBrush" Color="White" />
        <SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888″ />
        <SolidColorBrush x:Key="NormalBrush" Color="#888″ />
        <SolidColorBrush x:Key="NormalBorderBrush" Color="#888″ />
        <SolidColorBrush x:Key="HorizontalNormalBrush" Color="#888″ />
        <SolidColorBrush x:Key="HorizontalNormalBorderBrush" Color="#888″ />
        <LinearGradientBrush x:Key="ListBoxBackgroundBrush"
            StartPoint="0,0″ EndPoint="1,0.001″>
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="White" Offset="0.0″ />
                    <GradientStop Color="White" Offset="0.6″ />
                    <GradientStop Color="#DDDDDD" Offset="1.2″/>
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>
        <LinearGradientBrush x:Key="StandardBrush"
            StartPoint="0,0″ EndPoint="0,1″>
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#FFF" Offset="0.0″/>
                    <GradientStop Color="#CCC" Offset="1.0″/>
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>
        <SolidColorBrush x:Key="GlyphBrush" Color="#444″ />
        <LinearGradientBrush x:Key="PressedBrush"
            StartPoint="0,0″ EndPoint="0,1″>
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#BBB" Offset="0.0″/>
                    <GradientStop Color="#EEE" Offset="0.1″/>
                    <GradientStop Color="#EEE" Offset="0.9″/>
                    <GradientStop Color="#FFF" Offset="1.0″/>
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>

        <!– SrollViewer ScrollBar Repeat Buttons (at each end) –>
        <Style x:Key="ScrollBarLineButton" TargetType="{x:Type RepeatButton}">
            <Setter Property="SnapsToDevicePixels" Value="True"/>
            <Setter Property="OverridesDefaultStyle" Value="true"/>
            <Setter Property="Focusable" Value="false"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type RepeatButton}">
                        <Border
          Name="Border"
          Margin="1″
          CornerRadius="2″
          Background="{StaticResource NormalBrush}"
          BorderBrush="{StaticResource NormalBorderBrush}"
          BorderThickness="1″>
                            <Path
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Fill="{StaticResource GlyphBrush}"
            Data="{Binding Path=Content,
                RelativeSource={RelativeSource TemplatedParent}}" />
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsPressed" Value="true">
                                <Setter TargetName="Border" Property="Background"
                                Value="{StaticResource PressedBrush}" />
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Foreground"
                                Value="{StaticResource DisabledForegroundBrush}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <!– SrollViewer ScrollBar Repeat Buttons (The part in the middle, 
             not the thumb the long area between the buttons ) >
        <Style x:Key="ScrollBarPageButton" TargetType="{x:Type RepeatButton}">
            <Setter Property="SnapsToDevicePixels" Value="True"/>
            <Setter Property="OverridesDefaultStyle" Value="true"/>
            <Setter Property="IsTabStop" Value="false"/>
            <Setter Property="Focusable" Value="false"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type RepeatButton}">
                        <Border Background="Transparent" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <!– ScrollViewer ScrollBar Thumb, that part that can be dragged
            up/down or left/right Buttons >
        <Style x:Key="ScrollBarThumb" TargetType="{x:Type Thumb}">
            <Setter Property="SnapsToDevicePixels" Value="True"/>
            <Setter Property="OverridesDefaultStyle" Value="true"/>
            <Setter Property="IsTabStop" Value="false"/>
            <Setter Property="Focusable" Value="false"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Thumb}">
                        <Border
          CornerRadius="2″
          Background="{TemplateBinding Background}"
          BorderBrush="{TemplateBinding BorderBrush}"
          BorderThickness="1″ />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <ControlTemplate x:Key="VerticalScrollBar"
            TargetType="{x:Type ScrollBar}">
            <Grid >
                <Grid.RowDefinitions>
                    <RowDefinition MaxHeight="18″/>
                    <RowDefinition Height="0.00001*"/>
                    <RowDefinition MaxHeight="18″/>
                </Grid.RowDefinitions>
                <Border
      Grid.RowSpan="3″
      CornerRadius="2″
      Background="#F0F0F0″ />
                <RepeatButton
      Grid.Row="0″
      Style="{StaticResource ScrollBarLineButton}"
      Height="18″
      Command="ScrollBar.LineUpCommand"
      Content="M 0 4 L 8 4 L 4 0 Z" />
                <Track
      Name="PART_Track"
      Grid.Row="1″
      IsDirectionReversed="true">
                    <Track.DecreaseRepeatButton>
                        <RepeatButton
          Style="{StaticResource ScrollBarPageButton}"
          Command="ScrollBar.PageUpCommand" />
                    </Track.DecreaseRepeatButton>
                    <Track.Thumb>
                        <Thumb
          Style="{StaticResource ScrollBarThumb}"
          Margin="1,0,1,0″
          Background="{StaticResource HorizontalNormalBrush}"
          BorderBrush="{StaticResource HorizontalNormalBorderBrush}" />
                    </Track.Thumb>
                    <Track.IncreaseRepeatButton>
                        <RepeatButton
          Style="{StaticResource ScrollBarPageButton}"
          Command="ScrollBar.PageDownCommand" />
                    </Track.IncreaseRepeatButton>
                </Track>
                <RepeatButton
      Grid.Row="3″
      Style="{StaticResource ScrollBarLineButton}"
      Height="18″
      Command="ScrollBar.LineDownCommand"
      Content="M 0 0 L 4 4 L 8 0 Z"/>
            </Grid>
        </ControlTemplate>
        <!– HorizontalScrollBar Template using the previously created Templates >
        <ControlTemplate x:Key="HorizontalScrollBar"
            TargetType="{x:Type ScrollBar}">
            <Grid >
                <Grid.ColumnDefinitions>
                    <ColumnDefinition MaxWidth="18″/>
                    <ColumnDefinition Width="0.00001*"/>
                    <ColumnDefinition MaxWidth="18″/>
                </Grid.ColumnDefinitions>
                <Border
      Grid.ColumnSpan="3″
      CornerRadius="2″
      Background="#F0F0F0″ />
                <RepeatButton
      Grid.Column="0″
      Style="{StaticResource ScrollBarLineButton}"
      Width="18″
      Command="ScrollBar.LineLeftCommand"
      Content="M 4 0 L 4 8 L 0 4 Z" />
                <Track
      Name="PART_Track"
      Grid.Column="1″
      IsDirectionReversed="False">
                    <Track.DecreaseRepeatButton>
                        <RepeatButton
          Style="{StaticResource ScrollBarPageButton}"
          Command="ScrollBar.PageLeftCommand" />
                    </Track.DecreaseRepeatButton>
                    <Track.Thumb>
                        <Thumb
          Style="{StaticResource ScrollBarThumb}"
          Margin="0,1,0,1″
          Background="{StaticResource NormalBrush}"
          BorderBrush="{StaticResource NormalBorderBrush}" />
                    </Track.Thumb>
                    <Track.IncreaseRepeatButton>
                        <RepeatButton
          Style="{StaticResource ScrollBarPageButton}"
          Command="ScrollBar.PageRightCommand" />
                    </Track.IncreaseRepeatButton>
                </Track>
                <RepeatButton
      Grid.Column="3″
      Style="{StaticResource ScrollBarLineButton}"
      Width="18″
      Command="ScrollBar.LineRightCommand"
      Content="M 0 0 L 4 4 L 0 8 Z"/>
            </Grid>
        </ControlTemplate>
        <!– Style for overall  ScrollBar >
        <Style x:Key="{x:Type ScrollBar}" TargetType="{x:Type ScrollBar}">
            <Setter Property="SnapsToDevicePixels" Value="True"/>
            <Setter Property="OverridesDefaultStyle" Value="true"/>
            <Style.Triggers>
                <Trigger Property="Orientation" Value="Horizontal">
                    <Setter Property="Width" Value="Auto"/>
                    <Setter Property="Height" Value="18″ />
                    <Setter Property="Template"
                        Value="{StaticResource HorizontalScrollBar}" />
                </Trigger>
                <Trigger Property="Orientation" Value="Vertical">
                    <Setter Property="Width" Value="18″/>
                    <Setter Property="Height" Value="Auto" />
                    <Setter Property="Template"
                        Value="{StaticResource VerticalScrollBar}" />
                </Trigger>
            </Style.Triggers>
        </Style>

        <!– Style for overall  ScrollViewer >
        <Style x:Key="FavsScrollViewer" TargetType="{x:Type ScrollViewer}">
            <Setter Property="OverridesDefaultStyle" Value="True"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ScrollViewer}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition/>
                                <RowDefinition Height="Auto"/>
                            </Grid.RowDefinitions>

                            <ScrollContentPresenter Grid.Column="1″/>

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

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

  </Window.Resources>

    <Grid x:Name="LayoutRoot">
        <ScrollViewer     RenderTransformOrigin="0.5,0.5″ HorizontalAlignment="Stretch"
                        Margin="0,0,0,0″
                        Width="Auto" HorizontalScrollBarVisibility="Visible"
                        Style="{StaticResource FavsScrollViewer}">
         </ScrollViewer>
    </Grid>
</Window>

And if you want to try this for yourself, here is a VS 2008 demo project.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)

- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence

Both of these at Sussex University UK.

Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2016
  • Codeproject MVP 2016
  • Microsoft C# MVP 2015
  • Codeproject MVP 2015
  • Microsoft C# MVP 2014
  • Codeproject MVP 2014
  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Comments and Discussions

 
QuestionAdd Button Pin
Maheswari_Pandian9-Jul-14 18:50
Maheswari_Pandian9-Jul-14 18:50 
QuestionRight Side Scroll Pin
DEEPAK N R31-Dec-13 1:13
DEEPAK N R31-Dec-13 1:13 
AnswerRe: Right Side Scroll Pin
Sacha Barber5-Jan-14 4:56
Sacha Barber5-Jan-14 4:56 
QuestionImage styling in the scrollbar Pin
rasteron@live.com23-Mar-13 13:02
rasteron@live.com23-Mar-13 13:02 
AnswerRe: Image styling in the scrollbar Pin
Sacha Barber23-Mar-13 13:22
Sacha Barber23-Mar-13 13:22 
GeneralRe: Image styling in the scrollbar Pin
rasteron@live.com24-Mar-13 21:12
rasteron@live.com24-Mar-13 21:12 
QuestionRight Scrollbar Pin
rasteron@live.com23-Mar-13 5:31
rasteron@live.com23-Mar-13 5:31 
AnswerRe: Right Scrollbar Pin
Sacha Barber23-Mar-13 6:41
Sacha Barber23-Mar-13 6:41 
GeneralRe: Right Scrollbar Pin
rasteron@live.com23-Mar-13 12:58
rasteron@live.com23-Mar-13 12:58 
QuestionGmail password compromised Pin
Jibrohni20-Dec-12 22:57
Jibrohni20-Dec-12 22:57 
AnswerRe: Gmail password compromised Pin
Sacha Barber20-Dec-12 23:16
Sacha Barber20-Dec-12 23:16 
NewsWPF Composites Pin
prendebp29-Sep-12 23:13
prendebp29-Sep-12 23:13 
GeneralRe: WPF Anti-DataBinding Anti-DataTemplate Extensions Pin
Sacha Barber30-Sep-12 4:59
Sacha Barber30-Sep-12 4:59 
GeneralRe: WPF Anti-DataBinding Anti-DataTemplate Extensions Pin
prendebp25-Nov-12 11:11
prendebp25-Nov-12 11:11 
Sacha,

Thanks for checking it out, it is maturing rapidly! You may find it more palatable as it comes together and improves, who knows?
GeneralRe: WPF Anti-DataBinding Anti-DataTemplate Extensions Pin
Sacha Barber30-Sep-12 5:02
Sacha Barber30-Sep-12 5:02 
GeneralRe: WPF Anti-DataBinding Anti-DataTemplate Extensions Pin
prendebp25-Nov-12 11:15
prendebp25-Nov-12 11:15 
QuestionHow can I update the scrollbar's background color dynamically? Pin
bian12314-Jun-12 7:44
bian12314-Jun-12 7:44 
AnswerRe: How can I update the scrollbar's background color dynamically? Pin
Sacha Barber25-Oct-12 7:42
Sacha Barber25-Oct-12 7:42 
QuestionHow to use it in a listview? Pin
caioshin11-Jun-12 10:50
caioshin11-Jun-12 10:50 
AnswerRe: How to use it in a listview? Pin
Sacha Barber11-Jun-12 21:55
Sacha Barber11-Jun-12 21:55 
QuestionHow to make the bottom right hand corner rectangle transparent? Pin
IbrarM27-Apr-12 2:36
IbrarM27-Apr-12 2:36 
AnswerRe: How to make the bottom right hand corner rectangle transparent? Pin
Sacha Barber27-Apr-12 20:15
Sacha Barber27-Apr-12 20:15 
GeneralRe: How to make the bottom right hand corner rectangle transparent? Pin
IbrarM30-Apr-12 4:01
IbrarM30-Apr-12 4:01 
GeneralChanging scrollbar a little Pin
Lutosław13-Mar-11 6:17
Lutosław13-Mar-11 6:17 
GeneralRe: Changing scrollbar a little Pin
Sacha Barber13-Mar-11 20:58
Sacha Barber13-Mar-11 20:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.