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!