This is a migrated thread and some comments may be shown as answers.

Ticks offset to selected Value (ranged)

2 Answers 174 Views
Slider
This is a migrated thread and some comments may be shown as answers.
Robert
Top achievements
Rank 1
Robert asked on 08 Nov 2019, 03:13 PM

Hello,

I want to provide a Radslider with ranged selection, but I have an issue with the ticks.

As you can see on the screenshots I provided (Min and Max show the selected value in them), the offset of the ticks to the actual selection can be quite heavy on the first thumb.

I assume this is because you want to enable people to selecte a range from one value to the exact same value with both thumbs. However, in this case I do not need that and rather have the thumbs not be able to select the same value - and thus be able to have exact tick captions. Because as it is right now, users will not like it. It is counter-intuitive.

Is there any way right now to solve this issue?

Xaml-Code:

<StackPanel Grid.Row="1" Orientation="Vertical" Margin="8">
            <telerik:Label x:Name="sliderlabel" HorizontalAlignment="Center" HorizontalContentAlignment="Center" FontWeight="Bold" Margin="0"/>
            <telerik:RadSlider x:Name="slider" Orientation="Horizontal" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Margin="0"
                           IsDeferredDraggingEnabled="True" HandlesVisibility="Visible" IsSnapToTickEnabled="False" IsMoveToPointEnabled="False" MiddleThumbClickMode="DecreaseNearestThumb" IsSelectionRangeEnabled="True" AutoToolTipPlacement="BottomRight" TickPlacement="TopLeft"
                           SelectionStartChanged="Slider_SelectionStartChanged" SelectionEndChanged="Slider_SelectionEndChanged" DragCompleted="Slider_DragCompleted">
                <telerik:RadSlider.AutoToolTipContentTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding .,StringFormat=N0}"/>
                    </DataTemplate>
                </telerik:RadSlider.AutoToolTipContentTemplate>
                <telerik:RadSlider.TickTemplate>
                    <DataTemplate>
                        <Grid HorizontalAlignment="Left">
                            <TextBlock HorizontalAlignment="Left" TextAlignment="Left" Text="{Binding}" FontSize="10"/>
                        </Grid>
                    </DataTemplate>
                </telerik:RadSlider.TickTemplate>
            </telerik:RadSlider>
        </StackPanel>

2 Answers, 1 is accepted

Sort by
0
Robert
Top achievements
Rank 1
answered on 08 Nov 2019, 03:17 PM

Code-behind for the example:

 

slider.Minimum = 0;
slider.Maximum = 150;
slider.TickFrequency = 10;
0
Petar Mladenov
Telerik team
answered on 13 Nov 2019, 12:51 PM

Hi Robert,

I understand your requirement for disabling equality of selection start and end (resulting in empty range) and setting precise positions of thumbs according to ticks. Good news is that the first is easy to achieve with setting MinimumRangeSpan = 10 in your case. I admit it is a miss in our documentation and I logged it for improvement. However, the next requirement for better thumb positioning requires huge refactoring or several extensible additions to our RadSlider control. Quick note here - you can log a feature request in our feedback portal which we will later approve.

The selection thumbs and the rectangle (range rectangle which you can drag) between the thumbs are located in a horizontal stackpanel. When you drag the thumbs actually the slider's internal code changes the width of a 'invisible' buttons on left and right of the thumbs as well as width of a range rectangle. Here is a brief picture of the slider trakck (increase decrease handle buttons are not included):

                              Button Thumb Rectangle-Thumb Thumb Button

The code which handles these scenarios is pretty much locatied in the virtual method UpdateTrackLayout:

/// <summary> 
		/// This method will take the current min, max, and value to 
		/// calculate and layout the current control measurements.
		/// </summary> 
		protected virtual void UpdateTrackLayout()
		{
			if (this.IsInitializing)
			{
				return;
			}

			double range = this.Maximum - this.Minimum;
			if (range <= 0)
			{
				return;
			}
			double value = .0;

			Thickness margin = new Thickness();
			double coef = 1.0;

			if (this.IsSelectionRangeEnabled)
			{
				if (!this.IsArranged)
					return;
				value = this.IsDeferredDraggingEnabled ? this.DeferredSelectionStart : this.SelectionStart;
				double selectionStart = value;
				double selectionEnd = this.IsDeferredDraggingEnabled ? this.DeferredSelectionEnd : this.SelectionEnd;
				if (this.rangeStartThumb != null && this.rangeEndThumb != null && this.rangeMiddleThumb != null)
				{
					double rangeStartThumbWidth = this.thumbVisibility != System.Windows.Visibility.Collapsed ? this.rangeStartThumb.ActualWidth : 0d;
					double rangeEndThumbWidth = this.thumbVisibility != System.Windows.Visibility.Collapsed ? this.rangeStartThumb.ActualWidth : 0d;
					coef = this.baseTrackLength / range;
					margin = new Thickness(rangeStartThumbWidth, 0, rangeEndThumbWidth, 0);
					//// Prevent some rounding issues (due to pixel snapping)
					this.rangeMiddleThumb.Width = Math.Max(0, Math.Round(selectionEnd * coef) - Math.Round(selectionStart * coef));                    
                }
            }
			else
			{
				value = this.IsDeferredDraggingEnabled ? this.DeferredValue : this.Value;

				if (this.singleThumb != null)
				{
					var singThumblWidth = this.thumbVisibility != System.Windows.Visibility.Collapsed ? this.singleThumb.ActualWidth : 0d;
					coef = this.baseTrackLength / range;
					margin = new Thickness(singThumblWidth / 2, 0, singThumblWidth / 2, 0);
				}
			}

			if (this.bottomTickBar != null)
			{
				this.bottomTickBar.Margin = margin;
			}

			if (this.topTickBar != null)
			{
				this.topTickBar.Margin = margin;
			}

			if (this.largeDecrease != null)
			{
                if (value == this.Maximum)
                {
                    this.largeDecrease.Width = Math.Max(0, Math.Floor((value - this.Minimum) * coef));
                }
                else
                {
                    this.largeDecrease.Width = Math.Max(0, Math.Round(value * coef) - Math.Round(this.Minimum * coef));
                }
            }
		}

So if you decide to customize it we can help with getting the internal / private elements in it. Basically they are elements you can get in OnApplyTemplate.

Another option you can consider is somehow minimize the visual offsets this mechanism produces. In the attached project I have defined TickTemplate which uses both normal ticks and labels and also the left thumb has offset to the right and the opposite for the right thumb. I hope this can also be helpful in your scenario.

Regards,
Petar Mladenov
Progress Telerik

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Tags
Slider
Asked by
Robert
Top achievements
Rank 1
Answers by
Robert
Top achievements
Rank 1
Petar Mladenov
Telerik team
Share this question
or