StezPet
StezPet

Reputation: 2450

How to implement a custom slider with two thumbs?

How I can create a custom slider with two thumbs. One is for representing higher range and another for lower range. For example Price range. if the value is below 50 it will represent lower range and if it is above 50, it will represent the higher range.

Upvotes: 5

Views: 957

Answers (2)

alfah
alfah

Reputation: 2085

Based on @Jerry Nixon's code, I've created a range control. I do not know how to create a custom control. So have simply put the project in GitHub for all the desperate souls like me who are searching for a control :) Feel free to contribute or file issues. Will work on it as time permits.

https://github.com/alfah-plackal/CustomSlider

May the code be with you!

Upvotes: 2

Jerry Nixon
Jerry Nixon

Reputation: 31813

That's no small question. I won't do it all, but I will get you started:

<Grid Background="Black">
    <Grid Height="100" Width="500" Background="DimGray">
        <Grid.Resources>
            <Style TargetType="Grid" x:Name="HandleStyle">
                <Setter Property="Height" Value="50" />
                <Setter Property="Width" Value="50" />
                <Setter Property="Background" Value="White" />
                <Setter Property="RenderTransformOrigin" Value="0.5,0.5" />
            </Style>
            <Style TargetType="TextBlock" x:Name="HandleTextStyle">
                <Setter Property="Foreground" Value="DimGray" />
                <Setter Property="FontSize" Value="20" />
                <Setter Property="TextAlignment" Value="Center" />
                <Setter Property="HorizontalAlignment" Value="Center" />
                <Setter Property="VerticalAlignment" Value="Center" />
                <Setter Property="IsHitTestVisible" Value="False" />
            </Style>
        </Grid.Resources>
        <Rectangle Height="10" Width="450" Fill="DarkGray" />
        <Grid x:Name="LeftHandle" Style="{StaticResource HandleStyle}"
              ManipulationMode="TranslateX" 
              ManipulationDelta="LeftHandle_ManipulationDelta">
            <Grid.RenderTransform>
                <CompositeTransform TranslateX="-200"/>
            </Grid.RenderTransform>
            <TextBlock x:Name="LeftHandleText" Text="0"
                       Style="{StaticResource HandleTextStyle}" />
        </Grid>
        <Grid x:Name="RightHandle" Style="{StaticResource HandleStyle}"
              ManipulationMode="TranslateX" 
              ManipulationDelta="RightHandle_ManipulationDelta" RenderTransformOrigin="0.5,0.5">
            <Grid.RenderTransform>
                <CompositeTransform TranslateX="-150"/>
            </Grid.RenderTransform>
            <TextBlock x:Name="RightHandleText" Text="0"
                       Style="{StaticResource HandleTextStyle}" />
        </Grid>
    </Grid>
</Grid>

Use this code-behind:

int Min = 0;
int Max = 100;
int Size = 100;
int Range = 200;

private void LeftHandle_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
    var t = (sender as Grid).RenderTransform as CompositeTransform;
    var x = (RightHandle.RenderTransform as CompositeTransform).TranslateX;
    var f = -this.Range;
    var c = x - this.Size * .5;
    t.TranslateX = Translate(t, e, f, c);
    LeftHandleText.Text = Text(t.TranslateX);
}

private void RightHandle_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
    var t = (sender as Grid).RenderTransform as CompositeTransform;
    var x = (LeftHandle.RenderTransform as CompositeTransform).TranslateX;
    var f = x + this.Size * .5;
    var c = this.Range;
    t.TranslateX = Translate(t, e, f, c);
    RightHandleText.Text = Text(t.TranslateX);
}

private double Translate(CompositeTransform s, ManipulationDeltaRoutedEventArgs e, double floor, double ceiling)
{
    var target = s.TranslateX + e.Delta.Translation.X;
    if (target < floor)
        return floor;
    if (target > ceiling)
        return ceiling;
    return target;
}

private string Text(double x)
{
    var p = (x - (-this.Range)) / ((this.Range) - (-this.Range)) * 100d;
    var v = (this.Max - this.Min) * p / 100d + this.Min;
    return ((int)v).ToString();
}

Looks good:

enter image description here

Best of luck!

Upvotes: 6

Related Questions