Showing posts with label WPF. Show all posts
Showing posts with label WPF. Show all posts

Friday, July 26, 2013

Editable Button in WPF

Today I am going to share a code snippet to create an Editable Button in WPF, where we can update the text of a Button at runtime. In this control the user would right-click a button and then click 'Edit' to make to control Editable, and later right-click it to save/cancel the change.

First step to make the Button editable is to change the Style of Button and add a TextBox inside it, which we will make visible when the user clicks on 'Edit'.

01.<Style TargetType="my:EditableButton">
02.    <Setter Property="FocusVisualStyle">
03.        <Setter.Value>
04.            <Style>
05.                <Setter Property="Control.Template">
06.                    <Setter.Value>
07.                        <ControlTemplate>
08.                            <Rectangle Margin="2" SnapsToDevicePixels="True" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
09.                        </ControlTemplate>
10.                    </Setter.Value>
11.                </Setter>
12.            </Style>
13.        </Setter.Value>
14.    </Setter>
15.    <Setter Property="Background" Value="#FFDDDDDD"/>
16.    <Setter Property="BorderBrush" Value="#FF707070"/>
17.    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
18.    <Setter Property="BorderThickness" Value="1"/>
19.    <Setter Property="HorizontalContentAlignment" Value="Center"/>
20.    <Setter Property="VerticalContentAlignment" Value="Center"/>
21.    <Setter Property="Padding" Value="1"/>
22.    <Setter Property="Template">
23.        <Setter.Value>
24.            <ControlTemplate TargetType="{x:Type Button}">
25.                <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
26.                    <Grid>
27.                        <ContentPresenter x:Name="tbkContent" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
28.                        <TextBox   Name="txtContent" Height="{TemplateBinding Height}" TextAlignment="Center" Visibility="Collapsed" Text="{TemplateBinding Content}" Padding="0" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"  VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}"/>
29.                    </Grid>
30.                </Border>
31.                <ControlTemplate.Triggers>
32.                    <Trigger Property="IsDefaulted" Value="True">
33.                        <Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
34.                    </Trigger>
35.                    <Trigger Property="IsMouseOver" Value="True">
36.                        <Setter Property="Background" TargetName="border" Value="#FFBEE6FD"/>
37.                        <Setter Property="BorderBrush" TargetName="border" Value="#FF3C7FB1"/>
38.                    </Trigger>
39.                    <Trigger Property="IsPressed" Value="True">
40.                        <Setter Property="Background" TargetName="border" Value="#FFC4E5F6"/>
41.                        <Setter Property="BorderBrush" TargetName="border" Value="#FF2C628B"/>
42.                    </Trigger>
43.                    <Trigger Property="ToggleButton.IsChecked" Value="True">
44.                        <Setter Property="Background" TargetName="border" Value="#FFBCDDEE"/>
45.                        <Setter Property="BorderBrush" TargetName="border" Value="#FF245A83"/>
46.                    </Trigger>
47.                    <Trigger Property="IsEnabled" Value="False">
48.                        <Setter Property="Background" TargetName="border" Value="#FFF4F4F4"/>
49.                        <Setter Property="BorderBrush" TargetName="border" Value="#FFADB2B5"/>
50.                        <Setter Property="TextElement.Foreground" TargetName="tbkContent" Value="#FF838383"/>
51.                    </Trigger>
52.                </ControlTemplate.Triggers>
53.            </ControlTemplate>
54.        </Setter.Value>
55.    </Setter>
56.</Style>

As you can see in the above code, I have added a "txtContent" textbox which is hidden. Also to make editing look like a part of the Button, the Background and BorderBrush properties of textbox are transparent

01.Public Class EditableButton
02.    Inherits Button
03.    Private mButtonContentPresenter As ContentPresenter
04.    Private mButtonTextBox As TextBox
05. 
06.    Public Sub New()
07.        Me.DefaultStyleKey = GetType(EditableButton)
08.        AddHandler Me.Loaded, New RoutedEventHandler(AddressOf EditableButton_Loaded)
09.    End Sub
10. 
11.    Private Sub EditableButton_Loaded(sender As Object, e As RoutedEventArgs)
12. 
13.        Me.OnApplyTemplate()
14.    End Sub
15. 
16.    Public Overrides Sub OnApplyTemplate()
17.        MyBase.OnApplyTemplate()
18.        mButtonContentPresenter = DirectCast(Me.GetTemplateChild("tbkContent"), ContentPresenter)
19.        mButtonTextBox = DirectCast(Me.GetTemplateChild("txtContent"), TextBox)
20.        CreateSaveContextMenu()
21.        CreateEditContextMenu()
22.    End Sub
23. 
24.    Public Property IsEditMode() As Boolean
25.        Get
26.            Return CBool(GetValue(IsEditModeProperty))
27.        End Get
28.        Private Set(value As Boolean)
29.            SetValue(IsEditModeProperty, value)
30.        End Set
31.    End Property
32. 
33.    ' Using a DependencyProperty as the backing store for IsEditMode.  This enables animation, styling, binding, etc...
34.    Public Shared ReadOnly IsEditModeProperty As DependencyProperty = DependencyProperty.Register("IsEditMode", GetType(Boolean), GetType(EditableButton), New PropertyMetadata(False))
35. 
36.    Private Sub CreateSaveContextMenu()
37.        Dim menu As New ContextMenu
38.        Dim itm As New MenuItem()
39.        itm.Header = "Save"
40.        AddHandler itm.Click, New RoutedEventHandler(AddressOf itmSave_Click)
41.        menu.Items.Add(itm)
42. 
43.        itm = New MenuItem()
44.        itm.Header = "Cancel"
45.        AddHandler itm.Click, New RoutedEventHandler(AddressOf itmCancel_Click)
46.        menu.Items.Add(itm)
47. 
48.        ContextMenuService.SetContextMenu(mButtonTextBox, menu)
49.    End Sub
50. 
51. 
52. 
53.    Private Sub CreateEditContextMenu()
54.        Dim menu As New ContextMenu
55.        Dim itm As New MenuItem
56.        itm.Header = "Edit"
57.        AddHandler itm.Click, New RoutedEventHandler(AddressOf itmEdit_Click)
58.        menu.Items.Add(itm)
59. 
60.        ContextMenuService.SetContextMenu(mButtonContentPresenter, menu)
61.    End Sub
62. 
63.    Private Sub itmEdit_Click(sender As Object, e As RoutedEventArgs)
64.        mButtonContentPresenter.Visibility = Visibility.Collapsed
65.        mButtonTextBox.Visibility = Visibility.Visible
66.        IsEditMode = True
67.    End Sub
68. 
69.    Private Sub itmSave_Click(sender As Object, e As RoutedEventArgs)
70.        mButtonContentPresenter.Visibility = Visibility.Visible
71.        mButtonTextBox.Visibility = Visibility.Collapsed
72.        Me.Content = mButtonTextBox.Text
73.        IsEditMode = False
74.    End Sub
75. 
76.    Private Sub itmCancel_Click(sender As Object, e As RoutedEventArgs)
77.        mButtonContentPresenter.Visibility = Visibility.Visible
78.        mButtonTextBox.Visibility = Visibility.Collapsed
79.        IsEditMode = False
80.    End Sub
81.End Class

In the above code we have an "IsEditMode" property which the user can use to know whether the control is in Edit Mode or not. Also, we have two different Context Menus, one to Edit the Control, and the another to Save/Cancel the changes. Based on the menuitems that are clicked, we are going to set the visibility of TextBox and ContentPresenter, defined in XAML.

Now we can use the control in our application as below


01.<Window x:Class="MainWindow"
04.    xmlns:my="clr-namespace:WpfApplication1"
05.    Title="MainWindow" Height="350" Width="525">
06.   
07.    <Grid>
08.        <my:EditableButton x:Name="MyButton" Width="100" Height="25" Content="Edit Me"/>
09.    </Grid>
10.</Window>

Hope the above control helps you in your development.

Sunday, June 23, 2013

Set Brush for ScrollViewer Thumb

In WPF/Silverlight ScrollViewer and ScrollBar control doesn't have any property to change color of Thumb dynamically from XAML by setting property. We have to edit the Style of ScrollBar and set the Brush for it according to our requirement. Based on requirement of one of the user on MSDN Forum I decided to create a Custom ScrollViewer which has a property to set Brush for Thumb.

Public Class CustomScrollViewer
    Inherits ScrollViewer
  
    Shared Sub New()
        DefaultStyleKeyProperty.OverrideMetadata(GetType(CustomScrollViewer), New FrameworkPropertyMetadata(GetType(CustomScrollViewer)))
    End Sub
  
    Public Property ScrollBarThumbBrush As Brush
        Get
            Return GetValue(ScrollBarThumbBrushProperty)
        End Get
  
        Set(ByVal value As Brush)
            SetValue(ScrollBarThumbBrushProperty, value)
        End Set
    End Property
  
    Public Shared ReadOnly ScrollBarThumbBrushProperty As DependencyProperty = DependencyProperty.Register("ScrollBarThumbBrush", GetType(Brush), GetType(CustomScrollBar), New PropertyMetadata(Brushes.Gray))
  
End Class


In the above class, I have created a ScrollBarThumbBrush property which we can use to set Brush for Thumb in ScrollBar. And following in the XAML style for CustomScrollViewer control

<Style TargetType="my:CustomScrollViewer">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="my:CustomScrollViewer">
                <Grid x:Name="Grid" Background="{TemplateBinding Background}">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <Rectangle x:Name="Corner" Grid.Column="1" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Grid.Row="1"/>
                    <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" Margin="{TemplateBinding Padding}" Grid.Row="0"/>
                    <ScrollBar x:Name="PART_VerticalScrollBar"   AutomationProperties.AutomationId="VerticalScrollBar" Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Grid.Row="0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}"/>
                    <ScrollBar x:Name="PART_HorizontalScrollBar" AutomationProperties.AutomationId="HorizontalScrollBar" Cursor="Arrow" Grid.Column="0" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Orientation="Horizontal" Grid.Row="1" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Now to allow Thumb change color dynamically we need to change the Style of ScrollBar and read ScrollBarThumbBrush property. As you can see in above XAML Style CustomScrollViewer contains a ScrollBar control, so CustomScrollViewer is Ancestor of ScrollBar. So we are going to use following binding code to read ScrollBarThumbBrush property value in ScrollBar.

Fill="{Binding Path=ScrollBarThumbBrush, RelativeSource={RelativeSource AncestorType=my:CustomScrollViewer}}"

Below is the complete Style of ScrollBar control

<Style TargetType="ScrollBar">
    <Setter Property="Stylus.IsPressAndHoldEnabled" Value="False"/>
    <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
    <Setter Property="Background" Value="#FFF0F0F0"/>
    <Setter Property="BorderBrush" Value="#FFF0F0F0"/>
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    <Setter Property="BorderThickness" Value="1,0"/>
    <Setter Property="Width" Value="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"/>
    <Setter Property="MinWidth" Value="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ScrollBar">
                <Grid x:Name="Bg" SnapsToDevicePixels="True">
                    <Grid.RowDefinitions>
                        <RowDefinition MaxHeight="{DynamicResource {x:Static SystemParameters.VerticalScrollBarButtonHeightKey}}"/>
                        <RowDefinition Height="1E-05*"/>
                        <RowDefinition MaxHeight="{DynamicResource {x:Static SystemParameters.VerticalScrollBarButtonHeightKey}}"/>
                    </Grid.RowDefinitions>
                    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Row="1"/>
                    <RepeatButton x:Name="PART_LineUpButton" Command="ScrollBar.LineUpCommand" IsEnabled="{TemplateBinding IsMouseOver}">
                        <RepeatButton.Style>
                            <Style TargetType="{x:Type RepeatButton}">
                                <Setter Property="FocusVisualStyle">
                                    <Setter.Value>
                                        <Style>
                                            <Setter Property="Control.Template">
                                                <Setter.Value>
                                                    <ControlTemplate>
                                                        <Rectangle Margin="2" SnapsToDevicePixels="True" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
                                                    </ControlTemplate>
                                                </Setter.Value>
                                            </Setter>
                                        </Style>
                                    </Setter.Value>
                                </Setter>
                                <Setter Property="BorderThickness" Value="1"/>
                                <Setter Property="HorizontalContentAlignment" Value="Center"/>
                                <Setter Property="VerticalContentAlignment" Value="Center"/>
                                <Setter Property="Padding" Value="1"/>
                                <Setter Property="Focusable" Value="False"/>
                                <Setter Property="IsTabStop" Value="False"/>
                                <Setter Property="Template">
                                    <Setter.Value>
                                        <ControlTemplate TargetType="{x:Type RepeatButton}">
                                            <Border x:Name="border" BorderBrush="#FFF0F0F0" BorderThickness="1" Background="#FFF0F0F0" SnapsToDevicePixels="True">
                                                <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                            </Border>
                                            <ControlTemplate.Triggers>
                                                <Trigger Property="IsMouseOver" Value="True">
                                                    <Setter Property="Background" TargetName="border" Value="#FFDADADA"/>
                                                    <Setter Property="BorderBrush" TargetName="border" Value="#FFDADADA"/>
                                                </Trigger>
                                                <Trigger Property="IsPressed" Value="True">
                                                    <Setter Property="Background" TargetName="border" Value="#FF606060"/>
                                                    <Setter Property="BorderBrush" TargetName="border" Value="#FF606060"/>
                                                </Trigger>
                                                <Trigger Property="IsEnabled" Value="False">
                                                    <Setter Property="Opacity" TargetName="contentPresenter" Value="0.56"/>
                                                    <Setter Property="Background" TargetName="border" Value="#FFF0F0F0"/>
                                                    <Setter Property="BorderBrush" TargetName="border" Value="#FFF0F0F0"/>
                                                </Trigger>
                                            </ControlTemplate.Triggers>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </RepeatButton.Style>
                        <Path x:Name="ArrowTop" Data="M0,4C0,4 0,6 0,6 0,6 3.5,2.5 3.5,2.5 3.5,2.5 7,6 7,6 7,6 7,4 7,4 7,4 3.5,0.5 3.5,0.5 3.5,0.5 0,4 0,4z" Fill="#FF606060" Margin="3,4,3,3" Stretch="Uniform"/>
                    </RepeatButton>
                    <Track x:Name="PART_Track" IsDirectionReversed="True" IsEnabled="{TemplateBinding IsMouseOver}" Grid.Row="1">
                        <Track.DecreaseRepeatButton>
                            <RepeatButton Command="ScrollBar.PageUpCommand">
                                <RepeatButton.Style>
                                    <Style TargetType="{x:Type RepeatButton}">
                                        <Setter Property="OverridesDefaultStyle" Value="True"/>
                                        <Setter Property="Background" Value="Transparent"/>
                                        <Setter Property="Focusable" Value="False"/>
                                        <Setter Property="IsTabStop" Value="False"/>
                                        <Setter Property="Template">
                                            <Setter.Value>
                                                <ControlTemplate TargetType="{x:Type RepeatButton}">
                                                    <Rectangle Fill="{TemplateBinding Background}" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}"/>
                                                </ControlTemplate>
                                            </Setter.Value>
                                        </Setter>
                                    </Style>
                                </RepeatButton.Style>
                            </RepeatButton>
                        </Track.DecreaseRepeatButton>
                        <Track.IncreaseRepeatButton>
                            <RepeatButton Command="ScrollBar.PageDownCommand">
                                <RepeatButton.Style>
                                    <Style TargetType="{x:Type RepeatButton}">
                                        <Setter Property="OverridesDefaultStyle" Value="True"/>
                                        <Setter Property="Background" Value="Transparent"/>
                                        <Setter Property="Focusable" Value="False"/>
                                        <Setter Property="IsTabStop" Value="False"/>
                                        <Setter Property="Template">
                                            <Setter.Value>
                                                <ControlTemplate TargetType="{x:Type RepeatButton}">
                                                    <Rectangle Fill="{TemplateBinding Background}" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}"/>
                                                </ControlTemplate>
                                            </Setter.Value>
                                        </Setter>
                                    </Style>
                                </RepeatButton.Style>
                            </RepeatButton>
                        </Track.IncreaseRepeatButton>
                        <Track.Thumb>
                            <Thumb>
                                <Thumb.Style>
                                    <Style TargetType="{x:Type Thumb}">
                                        <Setter Property="OverridesDefaultStyle" Value="True"/>
                                        <Setter Property="IsTabStop" Value="False"/>
                                        <Setter Property="Template">
                                            <Setter.Value>
                                                <ControlTemplate TargetType="{x:Type Thumb}">
                                                    <Rectangle x:Name="rectangle" Fill="{Binding Path=ScrollBarThumbBrush, RelativeSource={RelativeSource AncestorType=my:CustomScrollViewer}}" Height="{TemplateBinding Height}" SnapsToDevicePixels="True" Width="{TemplateBinding Width}"/>
                                                    <ControlTemplate.Triggers>
                                                        <Trigger Property="IsMouseOver" Value="True">
                                                            <Setter Property="Fill" TargetName="rectangle" Value="#FFA6A6A6"/>
                                                        </Trigger>
                                                        <Trigger Property="IsDragging" Value="True">
                                                            <Setter Property="Fill" TargetName="rectangle" Value="#FF606060"/>
                                                        </Trigger>
                                                    </ControlTemplate.Triggers>
                                                </ControlTemplate>
                                            </Setter.Value>
                                        </Setter>
                                    </Style>
                                </Thumb.Style>
                            </Thumb>
                        </Track.Thumb>
                    </Track>
                    <RepeatButton x:Name="PART_LineDownButton" Command="ScrollBar.LineDownCommand" IsEnabled="{TemplateBinding IsMouseOver}" Grid.Row="2">
                        <RepeatButton.Style>
                            <Style TargetType="{x:Type RepeatButton}">
                                <Setter Property="FocusVisualStyle">
                                    <Setter.Value>
                                        <Style>
                                            <Setter Property="Control.Template">
                                                <Setter.Value>
                                                    <ControlTemplate>
                                                        <Rectangle Margin="2" SnapsToDevicePixels="True" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
                                                    </ControlTemplate>
                                                </Setter.Value>
                                            </Setter>
                                        </Style>
                                    </Setter.Value>
                                </Setter>
                                <Setter Property="BorderThickness" Value="1"/>
                                <Setter Property="HorizontalContentAlignment" Value="Center"/>
                                <Setter Property="VerticalContentAlignment" Value="Center"/>
                                <Setter Property="Padding" Value="1"/>
                                <Setter Property="Focusable" Value="False"/>
                                <Setter Property="IsTabStop" Value="False"/>
                                <Setter Property="Template">
                                    <Setter.Value>
                                        <ControlTemplate TargetType="{x:Type RepeatButton}">
                                            <Border x:Name="border" BorderBrush="#FFF0F0F0" BorderThickness="1" Background="#FFF0F0F0" SnapsToDevicePixels="True">
                                                <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                            </Border>
                                            <ControlTemplate.Triggers>
                                                <Trigger Property="IsMouseOver" Value="True">
                                                    <Setter Property="Background" TargetName="border" Value="#FFDADADA"/>
                                                    <Setter Property="BorderBrush" TargetName="border" Value="#FFDADADA"/>
                                                </Trigger>
                                                <Trigger Property="IsPressed" Value="True">
                                                    <Setter Property="Background" TargetName="border" Value="#FF606060"/>
                                                    <Setter Property="BorderBrush" TargetName="border" Value="#FF606060"/>
                                                </Trigger>
                                                <Trigger Property="IsEnabled" Value="False">
                                                    <Setter Property="Opacity" TargetName="contentPresenter" Value="0.56"/>
                                                    <Setter Property="Background" TargetName="border" Value="#FFF0F0F0"/>
                                                    <Setter Property="BorderBrush" TargetName="border" Value="#FFF0F0F0"/>
                                                </Trigger>
                                            </ControlTemplate.Triggers>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </RepeatButton.Style>
                        <Path x:Name="ArrowBottom" Data="M0,2.5C0,2.5 0,0.5 0,0.5 0,0.5 3.5,4 3.5,4 3.5,4 7,0.5 7,0.5 7,0.5 7,2.5 7,2.5 7,2.5 3.5,6 3.5,6 3.5,6 0,2.5 0,2.5z" Fill="#FF606060" Margin="3,4,3,3" Stretch="Uniform"/>
                    </RepeatButton>
                </Grid>
                <ControlTemplate.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding IsMouseOver, ElementName=PART_LineDownButton}" Value="true"/>
                            <Condition Binding="{Binding IsPressed, ElementName=PART_LineDownButton}" Value="true"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Fill" TargetName="ArrowBottom" Value="White"/>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding IsMouseOver, ElementName=PART_LineUpButton}" Value="true"/>
                            <Condition Binding="{Binding IsPressed, ElementName=PART_LineUpButton}" Value="true"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Fill" TargetName="ArrowTop" Value="White"/>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding IsMouseOver, ElementName=PART_LineDownButton}" Value="true"/>
                            <Condition Binding="{Binding IsPressed, ElementName=PART_LineDownButton}" Value="false"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Fill" TargetName="ArrowBottom" Value="Black"/>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding IsMouseOver, ElementName=PART_LineUpButton}" Value="true"/>
                            <Condition Binding="{Binding IsPressed, ElementName=PART_LineUpButton}" Value="false"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Fill" TargetName="ArrowTop" Value="Black"/>
                    </MultiDataTrigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Fill" TargetName="ArrowTop" Value="#FFBFBFBF"/>
                        <Setter Property="Fill" TargetName="ArrowBottom" Value="#FFBFBFBF"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="Orientation" Value="Horizontal">
            <Setter Property="Width" Value="Auto"/>
            <Setter Property="MinWidth" Value="0"/>
            <Setter Property="Height" Value="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarHeightKey}}"/>
            <Setter Property="MinHeight" Value="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarHeightKey}}"/>
            <Setter Property="BorderThickness" Value="0,1"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ScrollBar}">
                        <Grid x:Name="Bg" SnapsToDevicePixels="True">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition MaxWidth="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarButtonWidthKey}}"/>
                                <ColumnDefinition Width="1E-05*"/>
                                <ColumnDefinition MaxWidth="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarButtonWidthKey}}"/>
                            </Grid.ColumnDefinitions>
                            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="1"/>
                            <RepeatButton x:Name="PART_LineLeftButton" Command="ScrollBar.LineLeftCommand" IsEnabled="{TemplateBinding IsMouseOver}">
                                <RepeatButton.Style>
                                    <Style TargetType="{x:Type RepeatButton}">
                                        <Setter Property="FocusVisualStyle">
                                            <Setter.Value>
                                                <Style>
                                                    <Setter Property="Control.Template">
                                                        <Setter.Value>
                                                            <ControlTemplate>
                                                                <Rectangle Margin="2" SnapsToDevicePixels="True" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
                                                            </ControlTemplate>
                                                        </Setter.Value>
                                                    </Setter>
                                                </Style>
                                            </Setter.Value>
                                        </Setter>
                                        <Setter Property="BorderThickness" Value="1"/>
                                        <Setter Property="HorizontalContentAlignment" Value="Center"/>
                                        <Setter Property="VerticalContentAlignment" Value="Center"/>
                                        <Setter Property="Padding" Value="1"/>
                                        <Setter Property="Focusable" Value="False"/>
                                        <Setter Property="IsTabStop" Value="False"/>
                                        <Setter Property="Template">
                                            <Setter.Value>
                                                <ControlTemplate TargetType="{x:Type RepeatButton}">
                                                    <Border x:Name="border" BorderBrush="#FFF0F0F0" BorderThickness="1" Background="#FFF0F0F0" SnapsToDevicePixels="True">
                                                        <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                                    </Border>
                                                    <ControlTemplate.Triggers>
                                                        <Trigger Property="IsMouseOver" Value="True">
                                                            <Setter Property="Background" TargetName="border" Value="#FFDADADA"/>
                                                            <Setter Property="BorderBrush" TargetName="border" Value="#FFDADADA"/>
                                                        </Trigger>
                                                        <Trigger Property="IsPressed" Value="True">
                                                            <Setter Property="Background" TargetName="border" Value="#FF606060"/>
                                                            <Setter Property="BorderBrush" TargetName="border" Value="#FF606060"/>
                                                        </Trigger>
                                                        <Trigger Property="IsEnabled" Value="False">
                                                            <Setter Property="Opacity" TargetName="contentPresenter" Value="0.56"/>
                                                            <Setter Property="Background" TargetName="border" Value="#FFF0F0F0"/>
                                                            <Setter Property="BorderBrush" TargetName="border" Value="#FFF0F0F0"/>
                                                        </Trigger>
                                                    </ControlTemplate.Triggers>
                                                </ControlTemplate>
                                            </Setter.Value>
                                        </Setter>
                                    </Style>
                                </RepeatButton.Style>
                                <Path x:Name="ArrowLeft" Data="M3.18,7C3.18,7 5,7 5,7 5,7 1.81,3.5 1.81,3.5 1.81,3.5 5,0 5,0 5,0 3.18,0 3.18,0 3.18,0 0,3.5 0,3.5 0,3.5 3.18,7 3.18,7z" Fill="#FF606060" Margin="3" Stretch="Uniform"/>
                            </RepeatButton>
                            <Track x:Name="PART_Track" Grid.Column="1" IsEnabled="{TemplateBinding IsMouseOver}">
                                <Track.DecreaseRepeatButton>
                                    <RepeatButton Command="ScrollBar.PageLeftCommand">
                                        <RepeatButton.Style>
                                            <Style TargetType="{x:Type RepeatButton}">
                                                <Setter Property="OverridesDefaultStyle" Value="True"/>
                                                <Setter Property="Background" Value="Transparent"/>
                                                <Setter Property="Focusable" Value="False"/>
                                                <Setter Property="IsTabStop" Value="False"/>
                                                <Setter Property="Template">
                                                    <Setter.Value>
                                                        <ControlTemplate TargetType="{x:Type RepeatButton}">
                                                            <Rectangle Fill="{TemplateBinding Background}" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}"/>
                                                        </ControlTemplate>
                                                    </Setter.Value>
                                                </Setter>
                                            </Style>
                                        </RepeatButton.Style>
                                    </RepeatButton>
                                </Track.DecreaseRepeatButton>
                                <Track.IncreaseRepeatButton>
                                    <RepeatButton Command="ScrollBar.PageRightCommand">
                                        <RepeatButton.Style>
                                            <Style TargetType="{x:Type RepeatButton}">
                                                <Setter Property="OverridesDefaultStyle" Value="True"/>
                                                <Setter Property="Background" Value="Transparent"/>
                                                <Setter Property="Focusable" Value="False"/>
                                                <Setter Property="IsTabStop" Value="False"/>
                                                <Setter Property="Template">
                                                    <Setter.Value>
                                                        <ControlTemplate TargetType="{x:Type RepeatButton}">
                                                            <Rectangle Fill="{TemplateBinding Background}" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}"/>
                                                        </ControlTemplate>
                                                    </Setter.Value>
                                                </Setter>
                                            </Style>
                                        </RepeatButton.Style>
                                    </RepeatButton>
                                </Track.IncreaseRepeatButton>
                                <Track.Thumb>
                                    <Thumb>
                                        <Thumb.Style>
                                            <Style TargetType="{x:Type Thumb}">
                                                <Setter Property="OverridesDefaultStyle" Value="True"/>
                                                <Setter Property="IsTabStop" Value="False"/>
                                                <Setter Property="Template">
                                                    <Setter.Value>
                                                        <ControlTemplate TargetType="{x:Type Thumb}">
                                                            <Rectangle x:Name="rectangle" Fill="{Binding Path=ScrollBarThumbBrush, RelativeSource={RelativeSource AncestorType=my:CustomScrollViewer}}" Height="{TemplateBinding Height}" SnapsToDevicePixels="True" Width="{TemplateBinding Width}"/>
                                                            <ControlTemplate.Triggers>
                                                                <Trigger Property="IsMouseOver" Value="True">
                                                                    <Setter Property="Fill" TargetName="rectangle" Value="#FFA6A6A6"/>
                                                                </Trigger>
                                                                <Trigger Property="IsDragging" Value="True">
                                                                    <Setter Property="Fill" TargetName="rectangle" Value="#FF606060"/>
                                                                </Trigger>
                                                            </ControlTemplate.Triggers>
                                                        </ControlTemplate>
                                                    </Setter.Value>
                                                </Setter>
                                            </Style>
                                        </Thumb.Style>
                                    </Thumb>
                                </Track.Thumb>
                            </Track>
                            <RepeatButton x:Name="PART_LineRightButton" Grid.Column="2" Command="ScrollBar.LineRightCommand" IsEnabled="{TemplateBinding IsMouseOver}">
                                <RepeatButton.Style>
                                    <Style TargetType="{x:Type RepeatButton}">
                                        <Setter Property="FocusVisualStyle">
                                            <Setter.Value>
                                                <Style>
                                                    <Setter Property="Control.Template">
                                                        <Setter.Value>
                                                            <ControlTemplate>
                                                                <Rectangle Margin="2" SnapsToDevicePixels="True" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
                                                            </ControlTemplate>
                                                        </Setter.Value>
                                                    </Setter>
                                                </Style>
                                            </Setter.Value>
                                        </Setter>
                                        <Setter Property="BorderThickness" Value="1"/>
                                        <Setter Property="HorizontalContentAlignment" Value="Center"/>
                                        <Setter Property="VerticalContentAlignment" Value="Center"/>
                                        <Setter Property="Padding" Value="1"/>
                                        <Setter Property="Focusable" Value="False"/>
                                        <Setter Property="IsTabStop" Value="False"/>
                                        <Setter Property="Template">
                                            <Setter.Value>
                                                <ControlTemplate TargetType="{x:Type RepeatButton}">
                                                    <Border x:Name="border" BorderBrush="#FFF0F0F0" BorderThickness="1" Background="#FFF0F0F0" SnapsToDevicePixels="True">
                                                        <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                                    </Border>
                                                    <ControlTemplate.Triggers>
                                                        <Trigger Property="IsMouseOver" Value="True">
                                                            <Setter Property="Background" TargetName="border" Value="#FFDADADA"/>
                                                            <Setter Property="BorderBrush" TargetName="border" Value="#FFDADADA"/>
                                                        </Trigger>
                                                        <Trigger Property="IsPressed" Value="True">
                                                            <Setter Property="Background" TargetName="border" Value="#FF606060"/>
                                                            <Setter Property="BorderBrush" TargetName="border" Value="#FF606060"/>
                                                        </Trigger>
                                                        <Trigger Property="IsEnabled" Value="False">
                                                            <Setter Property="Opacity" TargetName="contentPresenter" Value="0.56"/>
                                                            <Setter Property="Background" TargetName="border" Value="#FFF0F0F0"/>
                                                            <Setter Property="BorderBrush" TargetName="border" Value="#FFF0F0F0"/>
                                                        </Trigger>
                                                    </ControlTemplate.Triggers>
                                                </ControlTemplate>
                                            </Setter.Value>
                                        </Setter>
                                    </Style>
                                </RepeatButton.Style>
                                <Path x:Name="ArrowRight" Data="M1.81,7C1.81,7 0,7 0,7 0,7 3.18,3.5 3.18,3.5 3.18,3.5 0,0 0,0 0,0 1.81,0 1.81,0 1.81,0 5,3.5 5,3.5 5,3.5 1.81,7 1.81,7z" Fill="#FF606060" Margin="3" Stretch="Uniform"/>
                            </RepeatButton>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition Binding="{Binding IsMouseOver, ElementName=PART_LineRightButton}" Value="true"/>
                                    <Condition Binding="{Binding IsPressed, ElementName=PART_LineRightButton}" Value="true"/>
                                </MultiDataTrigger.Conditions>
                                <Setter Property="Fill" TargetName="ArrowRight" Value="White"/>
                            </MultiDataTrigger>
                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition Binding="{Binding IsMouseOver, ElementName=PART_LineLeftButton}" Value="true"/>
                                    <Condition Binding="{Binding IsPressed, ElementName=PART_LineLeftButton}" Value="true"/>
                                </MultiDataTrigger.Conditions>
                                <Setter Property="Fill" TargetName="ArrowLeft" Value="White"/>
                            </MultiDataTrigger>
                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition Binding="{Binding IsMouseOver, ElementName=PART_LineRightButton}" Value="true"/>
                                    <Condition Binding="{Binding IsPressed, ElementName=PART_LineRightButton}" Value="false"/>
                                </MultiDataTrigger.Conditions>
                                <Setter Property="Fill" TargetName="ArrowRight" Value="Black"/>
                            </MultiDataTrigger>
                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition Binding="{Binding IsMouseOver, ElementName=PART_LineLeftButton}" Value="true"/>
                                    <Condition Binding="{Binding IsPressed, ElementName=PART_LineLeftButton}" Value="false"/>
                                </MultiDataTrigger.Conditions>
                                <Setter Property="Fill" TargetName="ArrowLeft" Value="Black"/>
                            </MultiDataTrigger>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="Fill" TargetName="ArrowLeft" Value="#FFBFBFBF"/>
                                <Setter Property="Fill" TargetName="ArrowRight" Value="#FFBFBFBF"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Trigger>
    </Style.Triggers>
</Style>

Now we can use the CustomScrollViewer control and set ScrollBarThumbBrush property as shown in following code in the project where we need Thumb color as per our requirement.

<my:CustomScrollViewer ScrollBarThumbBrush="Blue"  HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible">
     <Grid Width="600" Height="600"/>
</my:CustomScrollViewer>