131

All too often I want a WPF slider that behaves like the System.Windows.Forms.TrackBar of old. That is, I want a slider that goes from X to Y but only allows the user to move it in discrete integer positions.

How does one do this in WPF since the Value property on the Slider is double?

ThinkingStiff
  • 64,767
  • 30
  • 146
  • 239
cplotts
  • 13,941
  • 9
  • 55
  • 66

4 Answers4

198

The simple answer is that you take advantage of the IsSnapToTickEnabled and TickFrequency properties. That is, turn snapping to ticks on and set the tick frequency to 1.

Or, in other words ... take advantage of ticks ... but you don't necessarily have to show the ticks that you are snapping to.

Check out the following piece of xaml:

<Slider
    Orientation="Vertical"
    Height="200"
    Minimum="0"
    Maximum="10"
    Value="0"
    IsSnapToTickEnabled="True"
    TickFrequency="1"
/>
Tim Pohlmann
  • 4,140
  • 3
  • 32
  • 61
cplotts
  • 13,941
  • 9
  • 55
  • 66
  • 1
    This answer should be the accepted one. Works like a charm. Thanks – Ashbay Sep 26 '13 at 14:48
  • Thanks @Ashbay ... at the time, I wanted to give someone else credit for the answer ... rather than just marking my own answer as accepted. – cplotts Sep 26 '13 at 17:28
  • It's under the Common section of the Properties dialog in designer, but on my machine, at least, it wasn't immediately visible because the Advanced subsection was collapsed and all too easy to overlook. – amonroejj Sep 19 '19 at 13:20
107

If you set your tick marks in the right way, you can use IsSnapToTickEnabled. This worked pretty well for me. See MSDN for details.

Brian Stewart
  • 9,157
  • 11
  • 54
  • 66
50

For those that want to snap to specific positions, you can also use the Ticks property:

<Slider Minimum="1" Maximum="500" IsSnapToTickEnabled="True" Ticks="1,100,200,350,500" />
Dave
  • 14,618
  • 13
  • 91
  • 145
12

The snap trick is handy but has limitations, for instance if you want to only show a subset of valid ticks. I've had success with two alternatives: either bind to an integer or round the new value. Here is a combined example:

public int MyProperty { get; set; }

private void slider1_ValueChanged(object sender,
    RoutedPropertyChangedEventArgs<double> e)
{
    (sender as Slider).Value = Math.Round(e.NewValue, 0);
}

<Slider
    Name="slider1"
    TickPlacement="TopLeft"
    AutoToolTipPlacement="BottomRight"
    ValueChanged="slider1_ValueChanged"
    Value="{Binding MyProperty}"
    Minimum="0" Maximum="100" SmallChange="1" LargeChange="10"
    Ticks="0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100"/>

I have no idea how the performance of either compares to the snap trick but I haven't had any trouble*.

*If you also bind the value of the slider to a type of text field you will experience that, every once in a while if using the mouse, the text field will show decimals. If you also bind to an int at the same time the empty string will cause a conversion exception to be thrown that briefly bogs down the UI. These issues haven't been severe enough for me to look for solutions.

mkjeldsen
  • 2,053
  • 3
  • 23
  • 28
  • So does this allow the user to also have the other values on the slider? Or does it still only allow for the value of the ticks to be chosen. Kind of a weird question... hopefully you understand what I am asking. – JLott Feb 19 '13 at 20:18
  • 1
    @JLott: You can still only snap to the `Ticks` values (0, 10, 20, ...) but all the values in-between (1, 2, ...) are valid and can be selected with e.g. arrow keys. – mkjeldsen Feb 20 '13 at 06:45
  • This works for Silverlight where there is no `IsSnapToTickEnabled` property. – ΩmegaMan Jun 22 '15 at 20:40