WPF Elements: Custom DualSlider tick mark style
The Mindscape WPF DualSlider has various features related to displaying tick marks similar to that provided by the standard WPF Slider control. The TickSpacing property allows you to set the logical distance between each of the tick marks. A pair of boolean properties called ShowTopLeftTickMarks and ShowBottomRightTickMarks specifies whether the tick marks are displayed on the top, bottom, or both edges of the slider track. Additionally, you can snap the slider thumbs to the tick marks by setting the SnapToTickMarks property to true. In this blog post we look at how to make a custom DualSlider style that has different sized tick marks based on their positions.
After setting the various properties mentioned above, the DualSlider controls generates a ReadOnlyCollection of doubles that can be acquired using the TickPositions property. This is a collection of physical positions that can be used in a style to place the tick marks. The numbers in the collection represent the distance from the left side of the slider track to each individual tick mark as illustrated below.
To style the tick marks, we can use the tick positions collection as the items source of an ItemsControl. Then we template each number to be a Border that only renders as a line on its right hand edge. The width of this border is a binding to the number itself which places the ‘tick mark’ in the correct place. Now, in order for us to render each tick mark with a different height, we start by making a class to represent an individual tick mark. Tick marks will need to know their position as well as their size which gives us the following class.
public class TickMark { public double Position { get; set; } public double Size { get; set; } }
Instead of filling an ItemsControl with a collection of positions, we now want to give it a collection of TickMark objects. This is easily achieved using a custom converter that will take the collection of positions and create instances of our TickMark objects. Within this converter, we will iterate through each of the positions and create a TickMark using the respective position. The size of each TickMark will be based on the index of the current position. Part of this converter class can be seen below.
// Size properties: public int Size0 { get; set; } ... public int Size9 { get; set; } // Convert method: public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { ReadOnlyCollection<double> positions = (ReadOnlyCollection<double>)value; IList<TickMark> tickMarks = new List<TickMark>(); int count = 0; foreach (double d in positions) { double size = GetSize(count % 10); TickMark tickMark = new TickMark() { Position = d, Size = size }; tickMarks.Add(tickMark); count++; } return tickMarks; } // Returns the size of a tick mark for the given modular interval. private int GetSize(int remainder) { switch (remainder) { case 0: return Size0; ... case 9: return Size9; } return 0; }
In the Convert method we use the ‘count’ variable to keep track of what index we are at within the loop. We perform the modular operation on this variable and use the result to select the size of the TickMark. The converter has 10 properties that will let us set the size to be given to each TickMark based on their modular index. This converter can be used in xaml as follows.
<local:TickMarkListConverter x:Key="TickMarkListConverter" Size0="9" Size5="6" /> <DataTemplate x:Key="HorizontalTickTemplate"> <Border BorderThickness="0,0,1,0" BorderBrush="Black" Height="{Binding Size}" MinWidth="1" Width="{Binding Position}" HorizontalAlignment="Left" VerticalAlignment="Top" /> </DataTemplate> <Style x:Key="HorizontalTickListStyle" TargetType="ItemsControl"> <Setter Property="ItemTemplate" Value="{StaticResource HorizontalTickTemplate}" /> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <Grid /> </ItemsPanelTemplate> </Setter.Value> </Setter> </Style>
When creating a DualSlider template, we can use an ItemsControl and set its ItemsSource to be a binding to the DualSlider.TickPositions property using the converter. The HorizontalTickTemplate as seen above uses the TickMark.Size property to set its height. Combining this with custom slider thumb and track styles can achieve results such as this:
Using this technique you can create all sorts of DualSlider styles involving tick marks with varying sizes or colors based on the requirements of your applications. A sample including all the source code for creating a custom DualSlider style in this way can be downloaded here. Let us know if you need help with styling any of the controls in WPF Elements by leaving a comment on this blog post or letting us know in the forum.
Click here to download the trial of WPF Elements.
Leave a Reply
Categories
BrainDump (1)
Community Code (4)
Events (16)
F# (14)
General (53)
Lab Samples (2)
LightSpeed (268)
MegaPack (8)
News (71)
NHibernate Designer (26)
Nightly news (53)
Phone Elements (24)
Products (87)
Projects (5)
Screencast (6)
SharePoint (3)
Silverlight (14)
Silverlight Elements (66)
SimpleDB Management Tools (20)
Visual Studio (9)
VS File Explorer (7)
Web Workbench (39)
WPF (44)
WPF Diagrams (57)
WPF Elements (110)
WPF Property Grid (32)


Tagged as 


Posted by Jason on 15 August 2010 


