-2

I am new to WPF and just learning it. I am trying to make a custom Slider in WPF. I want to get a result like this:
Desired result. But I get this:
Current result. My style for the slider looks like this:

<Style x:Key="Style_SliderLeftButton"
       TargetType="{x:Type RepeatButton}">
    <Style.Setters>
        <Setter Property="SnapsToDevicePixels"
                Value="True" />
        <Setter Property="OverridesDefaultStyle"
                Value="True" />
        <Setter Property="IsTabStop"
                Value="False" />
        <Setter Property="Focusable"
                Value="False" />
        <Setter Property="Background"
                Value="{DynamicResource Brush_OnBackground_OnSurface_High}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type RepeatButton}">
                    <Border Background="{TemplateBinding Background}"
                            Margin="8,0,-8,0"
                            CornerRadius="2"
                            Height="4" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style.Setters>
</Style>

<Style x:Key="Style_SliderRightButton"
       TargetType="{x:Type RepeatButton}">
    <Style.Setters>
        <Setter Property="SnapsToDevicePixels"
                Value="True" />
        <Setter Property="OverridesDefaultStyle"
                Value="True" />
        <Setter Property="IsTabStop"
                Value="False" />
        <Setter Property="Focusable"
                Value="False" />
        <Setter Property="Background"
                Value="Transparent" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type RepeatButton}">
                    <Border Background="{TemplateBinding Background}"
                            Margin="0,0,8,0"
                            CornerRadius="2"
                            Height="4" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style.Setters>
</Style>

<Style x:Key="Style_SliderThumb"
       TargetType="{x:Type Thumb}">
    <Style.Setters>
        <Setter Property="SnapsToDevicePixels"
                Value="True" />
        <Setter Property="OverridesDefaultStyle"
                Value="True" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Thumb}">
                    <StackPanel Orientation="Vertical">
                        <Grid>
                            <!-- Big point -->
                            <Ellipse Panel.ZIndex="0"
                                     Fill="{DynamicResource Brush_Primary}"
                                     StrokeThickness="0"
                                     Height="22"
                                     Width="22" />

                            <!-- Center point -->
                            <Ellipse Panel.ZIndex="1"
                                     Fill="{DynamicResource Brush_Background_Surface}"
                                     StrokeThickness="0"
                                     Height="6"
                                     Width="6" />

                            <Ellipse Panel.ZIndex="2"
                                     Fill="{DynamicResource Brush_Background_Primary}"
                                     StrokeThickness="0"
                                     Height="6"
                                     Width="6" />

                            <Ellipse Panel.ZIndex="3"
                                     Fill="{DynamicResource Brush_Surface_Overlay_08dp}"
                                     StrokeThickness="0"
                                     Height="6"
                                     Width="6" />

                        </Grid>
                        <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Slider}, Path=Value}"
                                   FontSize="14"
                                   FontWeight="SemiBold"
                                   FontFamily="{DynamicResource Font_Montserrat}"
                                   Foreground="{DynamicResource Brush_OnBackground_OnSurface_High}"
                                   Background="Transparent"
                                   TextAlignment="Center"
                                   Margin="0,7,0,0"
                                   HorizontalAlignment="Center"
                                   VerticalAlignment="Top" />
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style.Setters>
</Style>

<!--Template when the orientation of the Slider is Horizontal.-->
<ControlTemplate x:Key="HorizontalSlider"
                 TargetType="{x:Type Slider}">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto"
                           MinHeight="{TemplateBinding MinHeight}" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <TickBar x:Name="TopTick"
                 SnapsToDevicePixels="True"
                 Placement="Top"
                 Height="4"
                 Visibility="Collapsed"
                 Fill="{DynamicResource Brush_OnBackground_OnSurface_Medium}" />

        <Border x:Name="TrackBackground"
                Margin="8,0"
                CornerRadius="2"
                Height="4"
                Grid.Row="1"
                BorderThickness="0"
                Background="{DynamicResource Brush_OnBackground_OnSurface_Medium}" />

        <Track Grid.Row="1"
               x:Name="PART_Track">

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

            <Track.Thumb>
                <Thumb Style="{StaticResource Style_SliderThumb}" />
            </Track.Thumb>

            <Track.IncreaseRepeatButton>
                <RepeatButton Style="{StaticResource Style_SliderRightButton}"
                              Command="Slider.IncreaseLarge" />
            </Track.IncreaseRepeatButton>
        </Track>

        <TickBar x: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>

<!--Template when the orientation of the Slider is Vertical.-->
<ControlTemplate x:Key="VerticalSlider"
                 TargetType="{x:Type Slider}">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto"
                              MinWidth="{TemplateBinding MinWidth}" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>

        <TickBar x:Name="TopTick"
                 SnapsToDevicePixels="True"
                 Placement="Left"
                 Width="4"
                 Visibility="Collapsed"
                 Fill="{DynamicResource Brush_OnBackground_OnSurface_Medium}" />

        <Border x:Name="TrackBackground"
                Margin="0"
                CornerRadius="2"
                Width="4"
                Grid.Column="1"
                BorderThickness="1"
                Background="{DynamicResource Brush_OnBackground_OnSurface_Medium}" />
        
        <Track Grid.Column="1"
               x:Name="PART_Track">
            
            <Track.DecreaseRepeatButton>
                <RepeatButton Style="{StaticResource Style_SliderLeftButton}"
                              Command="Slider.DecreaseLarge" />
            </Track.DecreaseRepeatButton>
            
            <Track.Thumb>
                <Thumb Style="{StaticResource Style_SliderThumb}" />
            </Track.Thumb>
            
            <Track.IncreaseRepeatButton>
                <RepeatButton Style="{StaticResource Style_SliderRightButton}"
                              Command="Slider.IncreaseLarge" />
            </Track.IncreaseRepeatButton>
        </Track>
        
        <TickBar x: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>

I took the template from the documentation: https://learn.microsoft.com/en-us/dotnet/desktop/wpf/controls/slider-styles-and-templates?view=netframeworkdesktop-4.8. How could I achieve the desired result?

old_timer
  • 69,149
  • 8
  • 89
  • 168
Joel
  • 3
  • 2
  • To understand your template, could you add the brush resources that this Template uses to the code. It would also be very helpful if you could provide an example XAML that shows the screenshot you provided. – EldHasp Sep 10 '21 at 22:34

2 Answers2

0

Your thumb is centered, to change this, switch your stackpanel to grid. This will make the text overlap the ellipse. Do a render transform on your text to visually move it.


<TextBlock>
    <TextBlock.RenderTransform>
        <TranslateTransform X="0" Y="-30" />
    </TextBlock.RenderTransform>
</TextBlock>

0

If your real intention is to show the current value along with the Slider, you might be better off using the built-in ToolTip of Slider. It is customizable as follows:

<Slider AutoToolTipPlacement="BottomRight">
    <Slider.Resources>
        <Style TargetType="{x:Type ToolTip}" BasedOn="{StaticResource {x:Type ToolTip}}">
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="TextElement.Foreground" Value="White"/>
            <Setter Property="TextElement.FontWeight" Value="SemiBold"/>
        </Style>
    </Slider.Resources>
</Slider>
emoacht
  • 2,764
  • 1
  • 13
  • 24
  • What if I would like to always show the value of the slider? – Joel Sep 13 '21 at 12:32
  • There is no option to always show the built-in ToolTip. Back to your original question, you can adjust the vertical position of background bar setting `VerticalAlignment` to top and the top margin to appropriate value. Or user8934733's hack may work. – emoacht Sep 13 '21 at 21:15