Reputation: 2551
I'm using a WPF Slider control (I'm guessing the Silverlight version is similar) that's set to horizontal and has a Min Value of 0 and a Max Value of 5.
I'd like to display the values 0 - 5 below the tick marks to make it a bit more obvious which value the thumb is currently pointing to.
Is this possible and has anybody managed to achieve this?
Upvotes: 6
Views: 10762
Reputation: 1736
Adding a bit more detail to the above answer. This is how we did it, firstly edit the default Slider Control and generate the xaml in Blend.
Here is the entire style and yes instead of CustomTickBar replace the NumberedTickBar and use the Template for your Slider as Horizontal Slider as provided in the style.
<SolidColorBrush
x:Key="SliderThumb.Static.Foreground"
Color="#FFE5E5E5" />
<SolidColorBrush
x:Key="SliderThumb.MouseOver.Background"
Color="#FFDCECFC" />
<SolidColorBrush
x:Key="SliderThumb.MouseOver.Border"
Color="#FF7Eb4EA" />
<SolidColorBrush
x:Key="SliderThumb.Pressed.Background"
Color="#FFDAECFC" />
<SolidColorBrush
x:Key="SliderThumb.Pressed.Border"
Color="#FF569DE5" />
<SolidColorBrush
x:Key="SliderThumb.Disabled.Background"
Color="#FFF0F0F0" />
<SolidColorBrush
x:Key="SliderThumb.Disabled.Border"
Color="#FFD9D9D9" />
<SolidColorBrush
x:Key="SliderThumb.Static.Background"
Color="#FFF0F0F0" />
<SolidColorBrush
x:Key="SliderThumb.Static.Border"
Color="#FFACACAC" />
<SolidColorBrush
x:Key="SliderThumb.Track.Border"
Color="#FFD6D6D6" />
<SolidColorBrush
x:Key="SliderThumb.Track.Background"
Color="Red" />
<Style
x:Key="RepeatButtonTransparent"
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>
<Style
x:Key="SliderThumbStyle"
TargetType="{x:Type Thumb}">
<Setter
Property="SnapsToDevicePixels"
Value="true" />
<Setter
Property="OverridesDefaultStyle"
Value="true" />
<Setter
Property="Height"
Value="18" />
<Setter
Property="Width"
Value="18" />
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="{x:Type Thumb}">
<Ellipse
Name="Ellipse"
Fill="Orange"
Stroke="#404040"
StrokeThickness="1" />
<ControlTemplate.Triggers>
<Trigger
Property="IsMouseOver"
Value="True">
<Setter
TargetName="Ellipse"
Property="Fill"
Value="#FFC3C0FF" />
</Trigger>
<Trigger
Property="IsEnabled"
Value="false">
<Setter
TargetName="Ellipse"
Property="Fill"
Value="#EEEEEE" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate
x:Key="SliderThumbHorizontalDefault"
TargetType="{x:Type Thumb}">
<Grid
HorizontalAlignment="Center"
UseLayoutRounding="True"
VerticalAlignment="Center">
<Path
x:Name="grip"
Data="M 0,0 C0,0 11,0 11,0 11,0 11,18 11,18 11,18 0,18 0,18 0,18 0,0 0,0 z"
Fill="{StaticResource SliderThumb.Static.Background}"
Stretch="Fill"
SnapsToDevicePixels="True"
Stroke="{StaticResource SliderThumb.Static.Border}"
StrokeThickness="1"
UseLayoutRounding="True"
VerticalAlignment="Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger
Property="IsMouseOver"
Value="true">
<Setter
Property="Fill"
TargetName="grip"
Value="{StaticResource SliderThumb.MouseOver.Background}" />
<Setter
Property="Stroke"
TargetName="grip"
Value="{StaticResource SliderThumb.MouseOver.Border}" />
</Trigger>
<Trigger
Property="IsDragging"
Value="true">
<Setter
Property="Fill"
TargetName="grip"
Value="{StaticResource SliderThumb.Pressed.Background}" />
<Setter
Property="Stroke"
TargetName="grip"
Value="{StaticResource SliderThumb.Pressed.Border}" />
</Trigger>
<Trigger
Property="IsEnabled"
Value="false">
<Setter
Property="Fill"
TargetName="grip"
Value="{StaticResource SliderThumb.Disabled.Background}" />
<Setter
Property="Stroke"
TargetName="grip"
Value="{StaticResource SliderThumb.Disabled.Border}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<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>
<Custom:CustomTickBar
Margin="5,0,10,0"
x:Name="TopTick"
SnapsToDevicePixels="True"
Placement="Top"
Fill="Green"
Height="5" />
<Border
Name="TrackBackground"
Margin="0"
CornerRadius="2"
Height="4"
Grid.Row="1"
Background="{StaticResource SliderThumb.Track.Background}"
BorderBrush="{StaticResource SliderThumb.Track.Border}"
BorderThickness="1" />
<Track
Grid.Row="1"
Name="PART_Track">
<Track.DecreaseRepeatButton>
<RepeatButton
Style="{StaticResource RepeatButtonTransparent}"
Command="Slider.DecreaseLarge" />
</Track.DecreaseRepeatButton>
<Track.Thumb>
<Thumb
Style="{StaticResource SliderThumbStyle}" />
<!--<Thumb
Style="{StaticResource SliderThumbHorizontalDefault}" />-->
</Track.Thumb>
<Track.IncreaseRepeatButton>
<RepeatButton
Style="{StaticResource RepeatButtonTransparent}"
Command="Slider.IncreaseLarge" />
</Track.IncreaseRepeatButton>
</Track>
<TickBar
Name="BottomTick"
SnapsToDevicePixels="True"
Grid.Row="2"
Fill="Black"
Placement="Bottom"
Height="10"
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>
Upvotes: 0
Reputation: 8958
I believe the best way to do this is to create a custom TickBar control and override the Rendering of the ticks. Here is one way:
public class NumberedTickBar : TickBar
{
protected override void OnRender(DrawingContext dc)
{
Size size = new Size(base.ActualWidth,base.ActualHeight);
int tickCount = (int)((this.Maximum - this.Minimum) / this.TickFrequency) + 1;
if((this.Maximum - this.Minimum) % this.TickFrequency == 0)
tickCount -= 1;
Double tickFrequencySize;
// Calculate tick's setting
tickFrequencySize = (size.Width * this.TickFrequency / (this.Maximum - this.Minimum));
string text = "";
FormattedText formattedText = null;
double num = this.Maximum - this.Minimum;
int i = 0;
// Draw each tick text
for(i = 0;i <= tickCount;i++)
{
text = Convert.ToString(Convert.ToInt32(this.Minimum + this.TickFrequency * i),10);
formattedText = new FormattedText(text,CultureInfo.GetCultureInfo("en-us"),FlowDirection.LeftToRight,new Typeface("Verdana"),8,Brushes.Black);
dc.DrawText(formattedText,new Point((tickFrequencySize * i),30));
}
}
}
Then you'll have to create a custom style for your slider that uses your new Tickbar instead of the default tickbar.
If you are not sure how to create a style for a slider you can start with the windows example here. It's a very sophisticated one.
Then the only thing left to do is to replace the Top Tickbar with your new custom one. Basically change:
<TickBar Name="TopTick" SnapsToDevicePixels="True" Placement="Top" Fill="{StaticResource GlyphBrush}" Height="4" Visibility="Collapsed" />
to this:
<local:NumberedTickBar Name="TopTick" Margin="5,0,10,0" SnapsToDevicePixels="True" Grid.Row="0" Fill="{TemplateBinding Foreground}" Placement="Top" Height="4" Visibility="Collapsed"/>
The margin is important because that will ensure that your text is in the right place.
Your slider will be on the top with ticks just below it. A row of text will be displayed below the ticks.
Upvotes: 11