设置滚动条拇指大小

15

我正在尝试解决与 WPF 滚动条拇指元素大小相关的算法。

可以使用 Scrollbar.ViewportSize 属性来调整拇指元素的大小,但其大小又与 Scrollbar.MinimumScrollbar.Maximum 值有关。

到目前为止,我已经发现:

对于最小值和最大值为 010,ViewportSize 的值为:

0 - 拇指的最小大小
5 - 拇指大约为可用轨道的25%
10 - 拇指大约为可用轨道的50%
100 - 拇指大约为可用轨道的75%
1000 - 拇指大约为可用轨道的90%
10000 - 拇指填充了可用轨道。

[注:这些数字仅基于我的试错结果!]

理想情况下,我希望能够有一个算法,可以根据滚动条的最小值和最大值,将拇指大小设置为可用轨道大小的 x%。

有人能帮忙吗?

谢谢。


1
仅凭最小值和最大值无法确定滑块的尺寸,还需要相对视口大小(即 [Min, Max] 区间中有多少适合视口的部分):thumbSizePercent=Min( 100, 100*ViewportSize/(MaxValue-MinValue))。 - Andy
5个回答

16

1
如果您只需要相对大小:viewportSize = (maximum - minimum) * p / (1 - p),其中 p 介于 0.0 和 1.0 之间。 - Markus Jarderot
@MarkusJarderot:如果p=1会发生什么? - Joshua Frank
这是一份关于如何设置滚动条拇指大小的文档,附有示例。https://learn.microsoft.com/en-us/dotnet/framework/wpf/controls/how-to-customize-the-thumb-size-on-a-scrollbar - Mike Ward

4
在我的这一方面,我保留了最小的拇指长度,因为触摸输入需要最小尺寸的拇指才能进行触摸优化。
您可以定义一个ScrollViewer ControlTemplate,它将使用TouchScrollBar作为其水平和垂直滚动条。
有关数学方面的内容,请查看UpdateViewPort方法。
抱歉,我不认为显式设置滚动条拇指以覆盖轨道长度的百分比是必要的用例。
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
}

}


3
另一种设置拇指最小宽度或高度的方法请参见此处:http://msdn.microsoft.com/en-us/library/bb613595.aspx - Kolky
@Nadzzz:你的代码存在许多问题,并且根本不能按预期工作。最重要的是,当列表中项目数量改变时,你更改了ScrollBar的ViewportSize,但它永远不会再次被计算。这只能适用于静态布局和静态数据,而非在运行时稍微有所变化的情况。 - ygoe
@Kolky:微软的那个示例也不起作用。它会抛出各种异常。如果它能正常工作,我也不知道它是否会做正确的事情。我看不到其中任何MinHeight的逻辑。 - ygoe

3
这里有一种方法,可以覆盖所有滚动条的拇指最小宽度。使用此设置有两个重要原因。
1)这不会调整滚动条的RepeatButton大小。(为什么样式覆盖Track)
2)这将仅调整在ScrollBar中使用的Track控件的拇指大小。(为什么Track样式包含在ScrollBar样式中。)
<!-- Override for all styles -->
<Style TargetType="{x:Type ScrollBar}" BasedOn="{StaticResource {x:Type ScrollBar}}">
    <Style.Resources>
        <Style TargetType="{x:Type Track}">
            <Style.Resources>
                <System:Double x:Key="{x:Static SystemParameters.VerticalScrollBarButtonHeightKey}">48</System:Double>
                <System:Double x:Key="{x:Static SystemParameters.HorizontalScrollBarButtonWidthKey}">48</System:Double>
            </Style.Resources>
        </Style>
    </Style.Resources>
</Style>

<!-- Override for a certain control -->
<!-- The ScrollBar Style part in the middle can be safely ommited
if you can guarantee the control only uses Tracks for ScrollBars -->
<SomeControl>
    <SomeControl.Resources>
        <Style TargetType="{x:Type ScrollBar}" BasedOn="{StaticResource {x:Type ScrollBar}}">
            <Style.Resources>
                <Style TargetType="{x:Type Track}">
                    <Style.Resources>
                        <System:Double x:Key="{x:Static SystemParameters.VerticalScrollBarButtonHeightKey}">48</System:Double>
                        <System:Double x:Key="{x:Static SystemParameters.HorizontalScrollBarButtonWidthKey}">48</System:Double>
                    </Style.Resources>
                </Style>
            </Style.Resources>
        </Style>
    </SomeControl.Resources>
</SomeControl>

1
如果您正在寻找如何设置滚动条拇指的最小高度:
来自 Ian(真正的MVP)这里
scrollBar1.Track.ViewportSize = double.NaN;  
scrollBar1.Track.Thumb.Height = Math.Max(minThumbHeight, DataScrollBar.Track.Thumb.ActualHeight);

或者你知道的,添加100多行的XAML代码,因为天哪数据绑定!!1!

0

UWP的滚动条拇指大小:

    static void SetViewportSize(ScrollBar bar, double size)
    {
        var max = (bar.Maximum - bar.Minimum);
        bar.ViewportSize = size / (max - size) * max;
        bar.IsEnabled = (bar.ViewportSize >= 0 &&
            bar.ViewportSize != double.PositiveInfinity);
        InvalidateScrollBar(bar);
    }

    static void InvalidateScrollBar(ScrollBar bar)
    {
        var v = bar.Value;
        bar.Value = (bar.Value == bar.Maximum) ? bar.Minimum : bar.Maximum;
        bar.Value = v;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接