Setting the Scrollbar Thumb size Setting the Scrollbar Thumb size wpf wpf

Setting the Scrollbar Thumb size


From: http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.track(VS.90).aspx

thumbSize = (viewportSize/(maximum–minimum+viewportSize))×trackLength

or re-arranging for viewportSize:

viewportSize = thumbSize×(maximum-minimum)/(trackLength-thumbSize)

You've prob found this already but thought I'd post in case others end up here.


On my side, I preserved a minimum thumb length because touch inputs require a thumb of a minimum size to be touch optimized.

You can define a ScrollViewer ControlTemplate that will use the TouchScrollBar as its horisontal and vertical ScrollBar.

See UpdateViewPort method for the math.

Sorry, I don't see the use case for explicitly setting the scrollbar thumb to cover a percentage of the track length

public class TouchScrollBar : System.Windows.Controls.Primitives.ScrollBar{    #region Fields    #region Dependency properties    public static readonly DependencyProperty MinThumbLengthProperty =        DependencyProperty.Register        ("MinThumbLength", typeof(double), typeof(TouchScrollBar), new UIPropertyMetadata((double)0, OnMinThumbLengthPropertyChanged));    #endregion    private double? m_originalViewportSize;    #endregion    #region Properties    public double MinThumbLength    {        get { return (double)GetValue(MinThumbLengthProperty); }        set { SetValue(MinThumbLengthProperty, value); }    }    #endregion    #region Constructors    public TouchScrollBar()    {        SizeChanged += OnSizeChanged;    }    private bool m_trackSubscribed;    void OnSizeChanged(object sender, SizeChangedEventArgs e)    {        SubscribeTrack();    }    private void SubscribeTrack()    {        if (!m_trackSubscribed && Track != null)        {            Track.SizeChanged += OnTrackSizeChanged;            m_trackSubscribed = true;        }    }    #endregion    #region Protected and private methods    #region Event handlers    #region Dependency properties event handlers    private void OnMinThumbLengthPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)    {        TouchScrollBar instance = d as TouchScrollBar;        if(instance != null)        {            instance.OnMinThumbLengthChanged(e);        }    }    #endregion    protected void OnTrackSizeChanged(object sender, SizeChangedEventArgs e)    {        SubscribeTrack();        UpdateViewPort();    }    protected override void OnMaximumChanged(double oldMaximum, double newMaximum)    {        base.OnMaximumChanged(oldMaximum, newMaximum);        SubscribeTrack();        UpdateViewPort();    }    protected override void OnMinimumChanged(double oldMinimum, double newMinimum)    {        base.OnMinimumChanged(oldMinimum, newMinimum);        SubscribeTrack();        UpdateViewPort();    }    protected void OnMinThumbLengthChanged(DependencyPropertyChangedEventArgs e)    {        SubscribeTrack();        UpdateViewPort();    }    #endregion    private void UpdateViewPort()    {        if(Track != null)        {            if(m_originalViewportSize == null)            {                m_originalViewportSize = ViewportSize;            }            double trackLength = Orientation == Orientation.Vertical ? Track.ActualHeight : Track.ActualWidth;            double thumbHeight = m_originalViewportSize.Value / (Maximum - Minimum + m_originalViewportSize.Value) * trackLength;            if (thumbHeight < MinThumbLength && !double.IsNaN(thumbHeight))            {                ViewportSize = (MinThumbLength * (Maximum - Minimum)) / (trackLength + MinThumbLength);            }        }    }    #endregion}

}


If you're looking for how to set a minimum height for the scrollbar thumb:

From Ian (da real MVP) here:

scrollBar1.Track.ViewportSize = double.NaN;  scrollBar1.Track.Thumb.Height = Math.Max(minThumbHeight, DataScrollBar.Track.Thumb.ActualHeight);

Or you know, add 100+ lines of xaml code cause omgDATABINDING!!1!