Ticks offset to selected Value (ranged)

3 posts, 0 answers
  1. Robert
    Robert avatar
    2 posts
    Member since:
    Nov 2018

    Posted 08 Nov 2019 Link to this post

    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. Robert
    Robert avatar
    2 posts
    Member since:
    Nov 2018

    Posted 08 Nov 2019 in reply to Robert Link to this post

    Code-behind for the example:

     

    slider.Minimum = 0;
    slider.Maximum = 150;
    slider.TickFrequency = 10;
  3. Petar Mladenov
    Admin
    Petar Mladenov avatar
    3154 posts

    Posted 13 Nov 2019 Link to this post

    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.
Back to Top