How to change scrollbar repeatButton to image then thumb is moving. WPF xaml

2.3k Views Asked by At

I have to insert image in xaml, that if the thumb is on top it has to be like 1st image , the second image show, how it has to look like if thumb is in the middle, and 3rd - thumb in the bottom. So how to do it? Already I put two images (Yellow arrow to Top, Gray arrow to Bottom), but where to put another two (Yellow arrow to Bottom, Gray arrow to Top)? My code so far:

<Window x:Class="Scroll4.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Title="MainWindow" Height="350" Width="525">

<Window.Resources>
    <SolidColorBrush x:Key="Background" Color="Gray" />

    <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>

    <Style x:Key="ScrollBarThumb" TargetType="{x:Type Thumb}">
        <Setter Property="Panel.ZIndex" Value="1" />
        <Setter Property="SnapsToDevicePixels" Value="True"/>
        <Setter Property="OverridesDefaultStyle" Value="true"/>
        <Setter Property="IsTabStop" Value="false"/>
        <Setter Property="Focusable" Value="false"/>
        <Setter Property="Opacity" Value="0.7" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Thumb}">
                    <Border Name="Border"
              CornerRadius="3"
              Background="{StaticResource Background}"
              BorderBrush="Transparent"
              BorderThickness="1" />
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsDragging" Value="true">
                            <Setter TargetName="Border" Property="Background" Value="{StaticResource Background}" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <ControlTemplate x:Key="VerticalScrollBar" TargetType="{x:Type ScrollBar}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition MaxHeight="60"/>
                <RowDefinition Height="*"/>
                <RowDefinition MaxHeight="60"/>
            </Grid.RowDefinitions>
            <Border
                Grid.RowSpan="3"
                CornerRadius="2"
                Background="#F8F8F8"/>

            <RepeatButton                        
                Focusable="False" Content="Up"
           Height="60"
           Command="ScrollBar.LineUpCommand">
                <RepeatButton.Template>
                    <ControlTemplate>
                        <DockPanel>
                            <Image Source="/Scroll4;component/Resources/bg.slide-up-active.png"/>
                            <ContentPresenter/>
                        </DockPanel>
                    </ControlTemplate>
                </RepeatButton.Template>
            </RepeatButton>
            <Track
           Name="PART_Track"
           Grid.Row="1"

           IsDirectionReversed="True">
                <Track.DecreaseRepeatButton>
                    <RepeatButton
                        Style="{StaticResource ScrollBarPageButton}"
                     Margin="3,2,3,2"
                     Command="ScrollBar.PageUpCommand"/>
                </Track.DecreaseRepeatButton>
                <Track.Thumb>
                    <Thumb Style="{StaticResource ScrollBarThumb}">  
                    </Thumb>
                    </Track.Thumb>
                        <Track.IncreaseRepeatButton>
                    <RepeatButton
                        Style="{StaticResource ScrollBarPageButton}"
                     Margin="3,2,3,2"
                     Command="ScrollBar.PageDownCommand" />
                </Track.IncreaseRepeatButton>
            </Track>
            <RepeatButton
           Grid.Row="2"
                Focusable="False"
           Height="60"

           Command="ScrollBar.LineDownCommand"
           Content="Down">
                <RepeatButton.Template>
                    <ControlTemplate>
                        <DockPanel>
                            <Image Source="/Scroll4;component/Resources/bg.slide-down-disabled.png"/>
                        </DockPanel>
                    </ControlTemplate>
                </RepeatButton.Template>
              </RepeatButton>

        </Grid>
    </ControlTemplate>
    <Style TargetType="ScrollBar">
        <Setter Property="SnapsToDevicePixels" Value="True"/>
        <Setter Property="OverridesDefaultStyle" Value="true"/>
        <Style.Triggers>
            <Trigger Property="Orientation" Value="Vertical">
                <Setter Property="Width" Value="60"/>
                <Setter Property="Height" Value="Auto" />
                <Setter Property="Template" Value="{StaticResource VerticalScrollBar}" />
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>


<Grid >
    <ScrollViewer Margin="89,94,183.4,90.8" RenderTransformOrigin="0.792,0.806" >

        <Image Source="/Scroll4;component/Resources/Football_grass.jpg"
               Stretch="Fill" Height="500" />

    </ScrollViewer>

</Grid>

1

There are 1 best solutions below

1
On BEST ANSWER

I would recommend you to do the following things:

  • At VerticalScrollBar ControlTemplate change images for both RepeatButton's to yellow ones
  • Set Images for RepeatButton's as its Content instead of creating Template
  • Add triggers to VerticalScrollBar. You should get VerticalOffset property. When it's 0 (ScrollViewer is on top) - change Content for up arrow to gray one. When VerticalOffset equals to ScrollableHeight - change Content for bottom arrow to gray one.

Also I would recommend you to use DrawingImages (vector graphics) instead of PNG, but it's up to you.

Example

<Window x:Class="Test31406472.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Test31406472"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <local:IsOnBottomConverter x:Key="isOnBottomConverter" />
    <DrawingImage x:Key="PrintIcon">
        <DrawingImage.Drawing>
            <DrawingGroup>
                <GeometryDrawing Geometry="M5.1,6.2V2.2c0-1,0.8-1.8,1.8-1.8h13.5c1,0,1.8,0.8,1.8,1.8v3.9H5.1
            L5.1,6.2z M4.2,20.6H3.3c-1.5,0-2.7-1.2-2.7-2.7V9.8c0-1.5,1.2-2.7,2.7-2.7h20.7c1.5,0,2.7,1.2,2.7,2.7v8.1
            c0,1.5-1.2,2.7-2.7,2.7h-0.9v-4.5H4.2V20.6L4.2,20.6L4.2,20.6z M5.1,17v7.2c0,1,0.8,1.8,1.8,1.8h13.5c1,0,1.8-0.8,1.8-1.8V17H5.1
            L5.1,17z M20.9,13.4c0.7,0,1.3-0.6,1.3-1.3c0-0.7-0.6-1.3-1.3-1.3s-1.3,0.6-1.3,1.3C19.6,12.8,20.2,13.4,20.9,13.4L20.9,13.4z"
                             Brush="#FF157EFB">
                </GeometryDrawing>
                <GeometryDrawing Brush="#FFFFFFFF">
                    <GeometryDrawing.Geometry>
                        <GeometryGroup>
                            <PathGeometry>
                                <PathGeometry.Figures>
                                    <PathFigureCollection>
                                        <PathFigure IsClosed="True" StartPoint="0,0">
                                            <PathFigure.Segments>
                                                <PathSegmentCollection>
                                                    <LineSegment Point="19.6,22" />
                                                    <LineSegment Point="7.8,22" />
                                                    <LineSegment Point="7.8,22" />
                                                    <LineSegment Point="7.8,23" />
                                                    <LineSegment Point="19.6,23" />
                                                </PathSegmentCollection>
                                            </PathFigure.Segments>
                                        </PathFigure>
                                    </PathFigureCollection>
                                </PathGeometry.Figures>
                            </PathGeometry>
                        </GeometryGroup>
                    </GeometryDrawing.Geometry>
                </GeometryDrawing>
            </DrawingGroup>
        </DrawingImage.Drawing>
    </DrawingImage>

    <SolidColorBrush x:Key="Background" Color="Gray" />

    <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>

    <Style x:Key="ScrollBarThumb" TargetType="{x:Type Thumb}">
        <Setter Property="Panel.ZIndex" Value="1" />
        <Setter Property="SnapsToDevicePixels" Value="True"/>
        <Setter Property="OverridesDefaultStyle" Value="true"/>
        <Setter Property="IsTabStop" Value="false"/>
        <Setter Property="Focusable" Value="false"/>
        <Setter Property="Opacity" Value="0.7" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Thumb}">
                    <Border Name="Border"
          CornerRadius="3"
          Background="{StaticResource Background}"
          BorderBrush="Transparent"
          BorderThickness="1" />
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsDragging" Value="true">
                            <Setter TargetName="Border" Property="Background" Value="{StaticResource Background}" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <ControlTemplate x:Key="VerticalScrollBar" TargetType="{x:Type ScrollBar}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition MaxHeight="60"/>
                <RowDefinition Height="*"/>
                <RowDefinition MaxHeight="60"/>
            </Grid.RowDefinitions>
            <Border
            Grid.RowSpan="3"
            CornerRadius="2"
            Background="#F8F8F8"/>

            <RepeatButton                        
            Focusable="False" Content="Up"
                Name="rbUp"
       Height="60"
       Command="ScrollBar.LineUpCommand">

            </RepeatButton>
            <Track
       Name="PART_Track"
       Grid.Row="1"

       IsDirectionReversed="True">
                <Track.DecreaseRepeatButton>
                    <RepeatButton
                    Style="{StaticResource ScrollBarPageButton}"
                 Margin="3,2,3,2"
                 Command="ScrollBar.PageUpCommand"/>
                </Track.DecreaseRepeatButton>
                <Track.Thumb>
                    <Thumb Style="{StaticResource ScrollBarThumb}">
                    </Thumb>
                </Track.Thumb>
                <Track.IncreaseRepeatButton>
                    <RepeatButton
                    Style="{StaticResource ScrollBarPageButton}"
                 Margin="3,2,3,2"
                 Command="ScrollBar.PageDownCommand" />
                </Track.IncreaseRepeatButton>
            </Track>
            <RepeatButton
       Grid.Row="2"
            Focusable="False"
       Height="60"
Name="rbDown"
       Command="ScrollBar.LineDownCommand"
       Content="Down">
            </RepeatButton>

        </Grid>
        <ControlTemplate.Triggers>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ScrollViewer}, Path=VerticalOffset}" Value="0">
                <Setter TargetName="rbUp" Property="Content" Value="!UP!" />
            </DataTrigger>
            <DataTrigger Value="True">
                <DataTrigger.Binding>
                    <MultiBinding Converter ="{StaticResource isOnBottomConverter}">
                        <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ScrollViewer}" Path="VerticalOffset"/>
                        <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ScrollViewer}" Path="ScrollableHeight"/>
                    </MultiBinding>
                </DataTrigger.Binding>
                <Setter TargetName="rbDown" Property="Content" Value="!DOWN!" />
            </DataTrigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
    <Style TargetType="ScrollBar">
        <Setter Property="SnapsToDevicePixels" Value="True"/>
        <Setter Property="OverridesDefaultStyle" Value="true"/>
        <Style.Triggers>
            <Trigger Property="Orientation" Value="Vertical">
                <Setter Property="Width" Value="60"/>
                <Setter Property="Height" Value="Auto" />
                <Setter Property="Template" Value="{StaticResource VerticalScrollBar}" />
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>


<Grid >
    <ScrollViewer Height="300">

        <Image Source="{StaticResource PrintIcon}"
           Stretch="Fill" Height="500" />

    </ScrollViewer>

</Grid>

And here's converter code:

public class IsOnBottomConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (values.Length == 2 && values[0] is double && values[1] is double)
        {
            return (double)values[0] == (double)values[1];
        }
        return false;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

All you need to do now is to change Content of Repeat buttons and Values in DataTriggers to ones you want.

Hope, it helps.