Home > OS >  Slider Thumb with TextBlock in WPF
Slider Thumb with TextBlock in WPF

Time:09-16

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://docs.microsoft.com/en-us/dotnet/desktop/wpf/controls/slider-styles-and-templates?view=netframeworkdesktop-4.8. How could I achieve the desired result?

CodePudding user response:

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>

CodePudding user response:

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