Create slider with different before / after thumb background color

Daniel Gilbert picture Daniel Gilbert · Sep 2, 2012 · Viewed 7.4k times · Source

I'm currently working on a media player. I'd like to create a slider like the one on this screen shot:

slider

What I've got up to now is this one:

current_slider

I'm currently struggeling with the light bar before the thumb. It changes it's length according to the thumb position. How can I implement this in WPF? Or should I try using a progressbar?

Atm, I have this code:

   <LinearGradientBrush x:Key="SliderThumbGradient" StartPoint="0,0" EndPoint="0,1">
    <GradientStop Offset="0" Color="#f7f7f7"/>
    <GradientStop Offset="1" Color="#bcbcbc"/>
</LinearGradientBrush>

<Style x:Key="SliderButtonStyle" 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="SliderThumbStyle" TargetType="{x:Type Thumb}">
    <Setter Property="SnapsToDevicePixels" Value="true"/>
    <Setter Property="OverridesDefaultStyle" Value="true"/>
    <Setter Property="Height" Value="14"/>
    <Setter Property="Width" Value="14"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Thumb}">
                <Ellipse 
      Name="Ellipse" 
      Fill="{DynamicResource SliderThumbGradient}"
      Stroke="#404040"
      StrokeThickness="1" />
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="Ellipse" Property="Fill" Value="#808080"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter TargetName="Ellipse" Property="Fill" Value="#EEEEEE"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<ControlTemplate x:Key="HorizontalSlider" TargetType="{x:Type Slider}">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto" MinHeight="{TemplateBinding Slider.MinHeight}"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <TickBar 
  Name="TopTick"
  SnapsToDevicePixels="True" 
  Placement="Top"
  Fill="#404040"
  Height="4"
  Visibility="Collapsed" />
        <Border 
  Name="TrackBackground"
  Margin="0"
  CornerRadius="6" 
  Height="12"
  Grid.Row="1"
  Background="#0a0a0a" 
  BorderBrush="#121212"
  BorderThickness="1" />
        <Track Grid.Row="1" Name="PART_Track">
            <Track.DecreaseRepeatButton>
                <RepeatButton 
      Style="{StaticResource SliderButtonStyle}"
      Command="Slider.DecreaseLarge" />
            </Track.DecreaseRepeatButton>
            <Track.Thumb>
                <Thumb Style="{StaticResource SliderThumbStyle}" />
            </Track.Thumb>
            <Track.IncreaseRepeatButton>
                <RepeatButton 
      Style="{StaticResource SliderButtonStyle}"
      Command="Slider.IncreaseLarge" />
            </Track.IncreaseRepeatButton>
        </Track>
        <TickBar 
  Name="BottomTick"
  SnapsToDevicePixels="True" 
  Grid.Row="2"
  Fill="{TemplateBinding Foreground}"
  Placement="Bottom"
  Height="4"
  Visibility="Collapsed" />
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="TickPlacement" Value="TopLeft">
            <Setter TargetName="TopTick" Property="Visibility" Value="Visible"/>
        </Trigger>
        <Trigger Property="TickPlacement" Value="BottomRight">
            <Setter TargetName="BottomTick" Property="Visibility" Value="Visible"/>
        </Trigger>
        <Trigger Property="TickPlacement" Value="Both">
            <Setter TargetName="TopTick" Property="Visibility" Value="Visible"/>
            <Setter TargetName="BottomTick" Property="Visibility" Value="Visible"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

<ControlTemplate x:Key="VerticalSlider" TargetType="{x:Type Slider}">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto" MinWidth="{TemplateBinding Slider.MinWidth}"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <TickBar 
  Name="TopTick"
  SnapsToDevicePixels="True" 
  Placement="Left"
  Fill="#404040"
  Width="4"
  Visibility="Collapsed" />
        <Border 
  Name="TrackBackground"
  Margin="0"
  CornerRadius="2" 
  Width="4"
  Grid.Column="1"
  Background="#E0E0E0" 
  BorderBrush="#404040"
  BorderThickness="1" />
        <Track Grid.Column="1" Name="PART_Track">
            <Track.DecreaseRepeatButton>
                <RepeatButton 
      Style="{StaticResource SliderButtonStyle}"
      Command="Slider.DecreaseLarge" />
            </Track.DecreaseRepeatButton>
            <Track.Thumb>
                <Thumb Style="{StaticResource SliderThumbStyle}" />
            </Track.Thumb>
            <Track.IncreaseRepeatButton>
                <RepeatButton 
      Style="{StaticResource SliderButtonStyle}"
      Command="Slider.IncreaseLarge" />
            </Track.IncreaseRepeatButton>
        </Track>
        <TickBar 
  Name="BottomTick"
  SnapsToDevicePixels="True" 
  Grid.Column="2"
  Fill="{TemplateBinding Foreground}"
  Placement="Right"
  Width="4"
  Visibility="Collapsed" />
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="TickPlacement" Value="TopLeft">
            <Setter TargetName="TopTick" Property="Visibility" Value="Visible"/>
        </Trigger>
        <Trigger Property="TickPlacement" Value="BottomRight">
            <Setter TargetName="BottomTick" Property="Visibility" Value="Visible"/>
        </Trigger>
        <Trigger Property="TickPlacement" Value="Both">
            <Setter TargetName="TopTick" Property="Visibility" Value="Visible"/>
            <Setter TargetName="BottomTick" Property="Visibility" Value="Visible"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

<Style TargetType="{x:Type Slider}">
    <Setter Property="SnapsToDevicePixels" Value="true"/>
    <Setter Property="OverridesDefaultStyle" Value="true"/>
    <Style.Triggers>
        <Trigger Property="Orientation" Value="Horizontal">
            <Setter Property="MinWidth" Value="104" />
            <Setter Property="MinHeight" Value="21" />
            <Setter Property="Template" Value="{StaticResource HorizontalSlider}" />
        </Trigger>
        <Trigger Property="Orientation" Value="Vertical">
            <Setter Property="MinWidth" Value="21" />
            <Setter Property="MinHeight" Value="104" />
            <Setter Property="Template" Value="{StaticResource VerticalSlider}" />
        </Trigger>
    </Style.Triggers>
</Style>

Answer

Mark Hall picture Mark Hall · Sep 2, 2012

The object that is changing its length on the left side is the DecreaseRepeatButton. You can implement the different color by creating a Style for it. Not sure how to get the concave edge on the right side though.

i.e.

<Style x:Key="DecreaseSliderButtonStyle" 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 Height="12" Background="DimGray" CornerRadius="6" Margin="0,0,-12,0" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

and in your ControlTemplate:

<Track.DecreaseRepeatButton>
    <RepeatButton 
        Style="{StaticResource DecreaseSliderButtonStyle}"
        Command="Slider.DecreaseLarge" />
</Track.DecreaseRepeatButton>