2

I am creating a "range slider" from three slider controls stacked on top of each other. The basic idea is from here which uses two sliders.

http://www.thejoyofcode.com/Creating_a_Range_Slider_in_WPF_and_other_cool_tips_and_tricks_for_UserControls_.aspx

I'm adding a third slider whose thumb will fill the space between the the thumbs from the other slider. The user will be able to drag this center thumb to move the two ends and maintain constant spacing between the two ends.

The XAML is simply three sliders. The secret to getting it to layer nicely is in using a control template (not reprodiced here. You can find it at the above URL).

<Grid VerticalAlignment="Top">
    <Border BorderThickness="0,1,0,0" BorderBrush="Green" VerticalAlignment="Center" Height="1" 
            Margin="5,0,5,0"/>

    <Slider x:Name="LowerSlider"
            Minimum="{Binding ElementName=root, Path=Minimum}"
            Maximum="{Binding ElementName=root, Path=Maximum}"
            Value="{Binding ElementName=root, Path=LowerValue, Mode=TwoWay}"
            Margin="0,0,0,0"
            Template="{StaticResource simpleSlider}"
            />
    
    <Slider x:Name="MiddleSlider"
            Minimum="{Binding ElementName=root, Path=Minimum}"
            Maximum="{Binding ElementName=root, Path=Maximum}"
            Value="{Binding ElementName=root, Path=MiddleValue, Mode=TwoWay}"
            Margin="10,0,0,0"
            Template="{StaticResource simpleSlider}"
            >
   </Slider>
    
    <Slider x:Name="UpperSlider"
            Minimum="{Binding ElementName=root, Path=Minimum}"
            Maximum="{Binding ElementName=root, Path=Maximum}"
            Value="{Binding ElementName=root, Path=UpperValue, Mode=TwoWay}"
            Margin="20,0,0,0"
            Template="{StaticResource simpleSlider}"
            />
</Grid>

As either outer thumb is dragged, I need to resize the center thumb to fill the space between the two end thumbs.

In the code behind, I can catch the movement of a thumb, and I can find the middle slider control, but I can't figure out how to programatically get to the thumb of the middle slider so that I can resize it to fill the space between the two outer thumbs.

private void UpperSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
         Slider slider= (Slider) this.FindName("MiddleSlider");
        // how to find the middleSlider thumb so I can set
        // it's width to fill the space between the outer thumbs
    }
GEOCHET
  • 21,119
  • 15
  • 74
  • 98
Mitch
  • 1,173
  • 1
  • 10
  • 15

2 Answers2

4

This should do it:

var track = (Track)slider.Template.FindName("PART_Track", slider);
var thumb = track.Thumb;
thumb.Width = fittingWidth;

(By the way, I would not do it this way, i would apply a MultiBinding to the two other sliders and a converter which calculates the width from that)

H.B.
  • 166,899
  • 29
  • 327
  • 400
  • Thanks @H.B. That's the concept I was missing. Just to complete the example for future readers, the thumb is also templated, so I needed to retrieve its representation in the same manner. – Mitch May 11 '11 at 14:50
  • I thought you only wanted to set the width? That should be possible without diving into the thumb's template. Anyway, if this answered your question you can accept it with the checkmark outline on the left of my answer. – H.B. May 11 '11 at 14:54
  • I just want to add that calculating the width of the middle thumb to fill the space between the two outer thumbs is complicated because as the thumb width increases, the the number of pixels that the thumb moves left and right decreases. This is because the slider stops the thumb when the left edge of the thumb reaches the left edge of the control. When the thumb is wider, the center of the thumb is shifts. The solution is to calculate the location, in pixels, of the two outer thumbs, then calculate the slider.Value, that will position the middle thumb between the two outer thumbs. – Mitch May 12 '11 at 15:29
  • `Track` is in the `System.Windows.Controls.Primitives` namespace. – Léon Pelletier Mar 07 '13 at 18:01
1
    private void UpperSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        Slider slider = (Slider) FindName("MiddleSlider");
        Track track = slider.Template.FindName("PART_Track", slider) as Track;
        if (track != null)
        {
            Rectangle thumbRectangle = track.Thumb.Template.FindName("Rect1", track.Thumb) as Rectangle;
            if (thumbRectangle != null)
            {
                thumbRectangle.Width = CalculateWidth();
            }
        }
    }
Mitch
  • 1,173
  • 1
  • 10
  • 15