3

I'd like to make a slider like this: Windows Phone Setting Page Slider

Notice there are little "|" between each slider values, and the user can only select those value.

But I found it is no use to set the SmallChange and LargeChange.

<TextBlock FontSize="44" Text="{Binding ElementName=ColorDarknessStepsSlider, Path=Value}"/>

<Slider x:Name="ColorDarknessStepsSlider" Margin="-12,0" Minimum="3" Maximum="5"
        SmallChange="1" LargeChange="1" />

I expect the user could only select 3, 4, 5 but It give me this:

My Slider

I don't know what's the problem. I am OK with no "|" mark between values, but at least the user must only select the integer value 3, 4, 5. How can I do this?

Edi Wang
  • 3,547
  • 6
  • 33
  • 51

4 Answers4

5

You can do that with xaml [EDIT : Exist only in WPF, appologies] :

    <Slider x:Name="ColorDarknessStepsSlider" Margin="-12,0" Minimum="3" Maximum="5"
    SmallChange="1" LargeChange="1" TickFrequency="1" />

Or via C# [EDIT : a good way]

    private void ColorDarknessStepsSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
         double roundedValue =  Math.Round(ColorDarknessStepsSlider.Value, 0);
         //Check if it is a rounded value
         if(ColorDarknessStepsSlider.Value != roundedValue )
             ColorDarknessStepsSlider.Value = roundedValue ;
    }

Hope it can help ;)

Error418
  • 309
  • 1
  • 11
  • thanks for you answer, but I believe there's no TickFrequency property in the Windows Phone's slider control.... – Edi Wang Apr 11 '14 at 13:21
  • @EdiWang, you're probably right, do you want only xaml solution? – Error418 Apr 11 '14 at 13:30
  • 1
    This C# code will hang the app - it's an infinite loop - one Change will inoke next one. Add a flag which will prevent from such a behaviour. – Romasz Apr 11 '14 at 14:47
  • @Error418 As I think now, it may work without the flag (some events aren't fired if the new value is the same as current) - it is a thing to try with debug mode as [MSDN](http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.rangebase.valuechanged.aspx) doesn't say clearly how it works. Nevertheless it is a thing worth checking. – Romasz Apr 11 '14 at 15:13
  • You can get the value and round it in a ManipulationCompleted event handler. Then the thumb doesn't snap to an integer location until the user lets go of it. I know that the "ease of access" slider doesn't do that on the phone, but it's worth mentioning because the slider in Windows Store apps doesn't snap to tick marks until letting go of the thumb. If you don't want multiple ValueChanged events because of the value change within this method/function, remove the handler before rounding and then set the handler again after the value has been set to the new value. – David Rector Sep 29 '15 at 20:09
3
  private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
  {
       int step = 40;
       (sender as Slider).Value = (e.NewValue % step != 0) ? (step - e.NewValue % step) + e.NewValue : e.NewValue;
  }

and xaml

<Slider Minimum="400" Maximum="2000" ValueChanged="Slider_ValueChanged"/>

Hope it help;)

0

For step length, use Minimum, Maximum, SmallChange

For those "ticks", try to play with TickFrequency and TickPlacement

Vitalii Vasylenko
  • 4,776
  • 5
  • 40
  • 64
0

Try using a converter - that's how I did it.

xaml change is

                <Slider x:Name="durationSlider" Margin="-12,0" Minimum="1" Maximum="12"
                    SmallChange="1" Value="{Binding Settings.Duration, Mode=TwoWay, Converter={StaticResource DoubleToIntConverter}}"/>                  


public class DoubleToIntConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        int rval = (int)value;
        if (value != null)
        {
            return rval;
        }
        return 0;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double val = (double)value;
        return (int)val;
    }

}

The binded field

    private int _duration;
    public int Duration
    {
        get
        {
            return _duration;
        }
        set
        {
            if (value != _duration)
            {
                _duration = value;
            }
            // Do this everytime because the initial input is a float converted down to an int
            NotifyPropertyChanged("Duration");
        }
    }