C# wpf ScrollBar自定义样式详解


前言

滚动条是一个常见控件,很多控件中都包含滚动条,比如ListBox、ComboBox、GridView等。wpf默认的滚动条的样式并不是特别好看,而且经常与UI设计的滚动条不一致,这个时候我们就需要自定义滚动条了。值得一提的是这,wpf的滚动条定制性和拓展性都非常好,这就为我们自定义滚动条提供了非常有利的条件。


一、ScrollBar的组成

ScrollBar由6个部分组成。两个行按钮、两个页按钮、一个滑块、一个轨道。

1.结构说明

一个简单的纵向滚动条如下:
在这里插入图片描述

纵向滚动组成如下:
在这里插入图片描述在这里插入图片描述

一个简单的纵向滚动条如下:
在这里插入图片描述

横向滚动条与纵向滚动条结构一致,相当于纵向滚动条顺时针转90度:
在这里插入图片描述
在这里插入图片描述

2.具体组成

行按钮

行按钮可以是任意按钮类型,且在ScrollBar内不受布局位置的限制,可以任意摆放。标识行按钮的方式是Command绑定ScrollBar的LineCommand
LineCommand有4种分别是:LineUpCommand、LineDownCommand、LineLeftCommand、LineRightCommand,共4个方向,分别两两对于纵向和横向的ScrollBar。
代码如下(示例):

(1)上行按钮
绑定ScrollBar.LineUpCommand即为上行按钮。

<RepeatButton Command="ScrollBar.LineUpCommand" />  

(2)下行按钮
绑定ScrollBar.LineDownCommand即为下行按钮。

<RepeatButton Command="ScrollBar.LineDownCommand" />

(3)左行按钮
绑定ScrollBar.LineLeftCommand即为左行按钮。

<RepeatButton Command="ScrollBar.LineLeftCommand" />

(4)右行按钮
绑定ScrollBar.LineRightCommand即为右行按钮。

<RepeatButton Command="ScrollBar.LineRightCommand" />

页按钮

页按钮相对于行按钮有布局的要求,需要放在Track标签的Track.DecreaseRepeatButton或中Track.IncreaseRepeatButton标签中(Track是轨道标签第4节会说明)。
页按钮只能是RepeatButton类型,并且Command绑定ScrollBar的PageCommand。PageCommand有4钟,分别是LineUpCommand、LineDownCommand、LineLeftCommand、LineRightCommand,共4个方向,分别两两对于纵向和横向的ScrollBar。
代码如下(示例):

上页按钮
放在Track.DecreaseRepeatButton标签里并绑定ScrollBar.PageUpCommand即为上页按钮。

<Track.DecreaseRepeatButton>
    <RepeatButton Command="ScrollBar.PageUpCommand" />
</Track.DecreaseRepeatButton>

下页按钮
放在Track.IncreaseRepeatButton标签里并绑定ScrollBar.PageDownCommand即为下页按钮。

<Track.IncreaseRepeatButton>
    <RepeatButton Command="ScrollBar.PageDownCommand" />
</Track.IncreaseRepeatButton>

左页按钮

放在Track.DecreaseRepeatButton标签里并绑定ScrollBar.PageLeftCommand即为左页按钮。

<Track.DecreaseRepeatButton>
    <RepeatButton Command="ScrollBar.PageLeftCommand" />
</Track.DecreaseRepeatButton>

右页按钮

放在Track.IncreaseRepeatButton标签里并绑定ScrollBar.PageRightCommand即为右页按钮。

<Track.IncreaseRepeatButton>
    <RepeatButton Command="ScrollBar.PageRightCommand" />    
</Track.IncreaseRepeatButton>

滑块

滑块必须是Thumb类型的标签,位置页必须放在Track的Track.Thumb子标签中(Track是轨道标签第4节会说明)。Thumb有Template属性,所以可以自定义样式。

<Track.Thumb>
    <Thumb/>      
</Track.Thumb>

Thumb的长度是自动计算的。其计算公式是:

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

如果想要Thumb固定长度,直接设置是没有效果的,必须先将Track的ViewportSize设置为NaN:

<Track ViewportSize="NaN" /> 

注:Thumb的长度是指,纵向滚动条Thumb的Height、横向滚动条Thumb的Width

轨道

ScrollBar的轨道是Track类型的标签,Track中包含了三部分:DecreaseRepeatButton、Thumb、IncreaseRepeatButton,分别对应页按钮和滑块。Track的Name属性必须设为 “PART_Track”,否则内部的按钮是无法控制滚动条的。

纵向轨道

<Track Name="PART_Track"  IsDirectionReversed="true">
    <Track.DecreaseRepeatButton>
        <RepeatButton Command="ScrollBar.PageUpCommand"/>
    </Track.DecreaseRepeatButton>
    <Track.Thumb>
        <Thumb/>
    </Track.Thumb>
    <Track.IncreaseRepeatButton>
        <RepeatButton  Command="ScrollBar.PageDownCommand"/>
    </Track.IncreaseRepeatButton>
</Track>

横向轨道

<Track  Name="PART_Track"  IsDirectionReversed="False">
    <Track.DecreaseRepeatButton>
        <RepeatButton Command="ScrollBar.PageLeftCommand"/>
    </Track.DecreaseRepeatButton>
    <Track.Thumb>
        <Thumb/>
    </Track.Thumb>
    <Track.IncreaseRepeatButton>
        <RepeatButton  Command="ScrollBar.PageRightCommand"/>
    </Track.IncreaseRepeatButton>
</Track>


二、如何自定义?

1.确定参数

第一步需要确定有哪些参数是可以自己控制的,否则将缺乏灵活性。比如有两个页面需要滚动条,样式是一样的,唯一的区别是滑块宽度不同,为此自定义两个不同的滚动条,显然是不明智的。更好的做法应该是,设置一个滑块宽度的参数,在不同页面使用不同的参数。
参数的定义可以根据具体使用需求,以及对ScrollBar可拓展性要求来确定。
比如定义如下参数(示例):

<!--纵向滚动条宽度-->
<sys:Double x:Key="VerticalScrollBarThickness">4</sys:Double>
<!--纵向轨道背景色-->
<SolidColorBrush x:Key="VerticalTrackBackgroundBrush" Color="White" />
<!--横向滚动条宽度-->
<sys:Double x:Key="HorizontalScrollBarThickness">4</sys:Double>
<!--横向轨道背景色-->
<SolidColorBrush x:Key="HorizontalTrackBackgroundBrush" Color="White" />

参数的用法说明:
参数对象在Style或Template中通过DynamicResource的方式使用,比如上面的VerticalScrollBarThickness对象在Style中通过 <Setter Property="Width" Value="{DynamicResource VerticalScrollBarThickness}" />的方式使用。或者在Template中<Border Width="{DynamicResource VerticalScrollBarThickness}" />
参数的赋值,是在Style使用处的Resources标签中定义同名的参数对象,并为其设置需要值。

2.定义Style

常规方法中,带ScrollBar的控件是无法获取到其ScrollBar对象并通过标签设置其属性的。在Style中自定义ScrollBar是比较好的方式。
定义Style标签有如下步骤:
(1)定义触发器
定义两个触发器,判段Orientation的属性,值为Vertical则设置纵向滚动条相关的属性值,反之值为Horizontal则设置横向向滚动条相关的属性值。
(2) 绑定参数
在上一节中有定义一些参数。在Style中就需要使用这些参数,一定要使用DynamicResource 去引用参数对象,否则将无法在页面使用时重新赋值。
(3)绑定Template
编写两个Template分别为VerticalScrollBar、HorizontalScrollBar(下一节有具体说明)。根据ScrollBar的Orientation属性来分别绑定不同的Template。
示例代码如下:

<Style x:Key="ScrollStyle_Example" TargetType="ScrollBar">
    <Style.Triggers>
        <Trigger Property="Orientation" Value="Horizontal">
            <Setter Property="Width" Value="Auto" />
            <Setter Property="Height" Value="{DynamicResource HorizontalScrollBarThickness}" />
            <Setter Property="Template" Value="{DynamicResource HorizontalScrollBar}" />
        </Trigger>
        <Trigger Property="Orientation" Value="Vertical">
            <Setter Property="Width" Value="{DynamicResource VerticalScrollBarThickness}" />
            <Setter Property="Height" Value="Auto" />
            <Setter Property="Template" Value="{DynamicResource VerticalScrollBar}" />
        </Trigger>
    </Style.Triggers>
</Style>

3.定义Template

一个完整的ScrollBar.Template有6个部分,即文章开头提到的:两个行按钮、两个页按钮、一个滑块、一个轨道。

(1) 纵向Template
对于纵向的Template代码如下(示例):

<ControlTemplate x:Key="VerticalScrollBar" TargetType="{x:Type RangeBase}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition MaxHeight="40"/>
                <RowDefinition Height="*"/>
                <RowDefinition MaxHeight="40"/>
            </Grid.RowDefinitions>
             <!--上行按钮-->
            <RepeatButton  Command="ScrollBar.LineUpCommand"/>
             <!--轨道-->
            <Track Name="PART_Track" Grid.Row="1">
                <Track.DecreaseRepeatButton>
                    <!--上页按钮-->
                    <RepeatButton Command="ScrollBar.PageUpCommand" />
                </Track.DecreaseRepeatButton>
                <Track.Thumb>
                    <!--滑块-->
                    <Thumb />
                </Track.Thumb>
                <Track.IncreaseRepeatButton>
                    <!--下页按钮-->
                    <RepeatButton Command="ScrollBar.PageDownCommand" />
                </Track.IncreaseRepeatButton>
            </Track>
            <!--下行按钮-->
            <RepeatButton Grid.Row="2" Command="ScrollBar.LineDownCommand"/>
        </Grid>
 </ControlTemplate>

(2)横向Template
对于横向的Template代码如下(示例):

<ControlTemplate x:Key="HorizontalScrollBar" TargetType="{x:Type RangeBase}">
        <Grid>
           <Grid.ColumnDefinitions>
                <ColumnDefinition Width="40"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition  Width="40"/>
            </Grid.ColumnDefinitions>
            <!--左行按钮-->
            <RepeatButton  Command="ScrollBar.LineLeftCommand"/>
            <!--轨道-->
            <Track Name="PART_Track" Grid.Column="1">
                <Track.DecreaseRepeatButton>
                    <!--左页按钮-->
                    <RepeatButton Command="ScrollBar.PageLeftCommand" />
                </Track.DecreaseRepeatButton>
                <Track.Thumb>
                    <!--滑块-->
                    <Thumb />
                </Track.Thumb>
                <Track.IncreaseRepeatButton>
                    <!--右页按钮-->
                    <RepeatButton Command="ScrollBar.PageRightCommand" />
                </Track.IncreaseRepeatButton>
            </Track>
            <!--右行按钮-->
            <RepeatButton Grid.Column="2" Command="ScrollBar.LineRightCommand"/>
        </Grid>
</ControlTemplate>

四、使用方法

在Resources标签中使用自定义滚动条。

1.继承Style

定义一个新的StyleTargetType为ScrollBar,BasedOn上述自定义的ScrollBar Style,不能设置x:key值

<Style TargetType="ScrollBar" BasedOn="{StaticResource ScrollStyle_Example}"></Style>

2.设置参数

根据第三章第1小节确定的参数,设置需要的参数值。比如将纵向滚动条宽度设为8像素:

<sys:Double x:Key="VerticalScrollBarThickness">8</sys:Double>

示例代码

以ListBox为例:

<ListBox>
    <ListBox.Resources>
        <!--替换ListBox中滚动条的样式-->
        <Style TargetType="ScrollBar" BasedOn="{StaticResource ScrollStyle_Example}"></Style>
        <!--纵向滚动条宽度为4像素-->
        <sys:Double x:Key="VerticalScrollBarThickness">4</sys:Double>
        <!--横向滚动条高度为4像素-->
        <sys:Double x:Key="HorizontalScrollBarThickness">4</sys:Double>
    </ListBox.Resources>
</ListBox>

五、具体例子

1.通用模板

根据上述步骤汇总出一个模板,对于ScrollBar的任何自定义拓展,都可以拷贝一份模板,在此模板的基础上定制修改。

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <!--  1.确定参数  -->
    <!--纵向滚动条宽度-->
    <sys:Double   x:Key="VerticalScrollBarThickness">4</sys:Double>
    <!--纵向滑块颜色-->
    <SolidColorBrush x:Key="VerticalTrackThumbBackgroundBrush" Color="#cccccc" />
    <!--横向滚动条宽度-->
    <sys:Double x:Key="HorizontalScrollBarThickness">4</sys:Double>
    <!--横向滑块颜色-->
    <SolidColorBrush x:Key="HorizontalTrackThumbBackgroundBrush" Color="#cccccc" />
    <!-- 2.定义Style  -->
    <Style x:Key="ScrollStyle_Example" TargetType="ScrollBar">
    <Setter Property="OverridesDefaultStyle" Value="true" />
        <Style.Triggers>
            <Trigger Property="Orientation" Value="Horizontal">
                <Setter Property="Width" Value="Auto" />
                <Setter Property="Height" Value="{DynamicResource HorizontalScrollBarThickness}" />
                <Setter Property="Template" Value="{DynamicResource HorizontalScrollBar}" />
            </Trigger>
            <Trigger Property="Orientation" Value="Vertical">
                <Setter Property="Width" Value="{DynamicResource VerticalScrollBarThickness}" />
                <Setter Property="Height" Value="Auto" />
                <Setter Property="Template" Value="{DynamicResource VerticalScrollBar}" />
            </Trigger>
        </Style.Triggers>
    </Style>
    <!-- 3.定义template  -->
    <!-- 纵向滚动条template  -->
    <ControlTemplate x:Key="VerticalScrollBar" TargetType="{x:Type RangeBase}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition MaxHeight="auto"/>
                <RowDefinition Height="*"/>
                <RowDefinition MaxHeight="auto"/>
            </Grid.RowDefinitions>
            <!--上行按钮-->
            <RepeatButton  Command="ScrollBar.LineUpCommand"/>
            <!--轨道-->
            <Track Name="PART_Track" Grid.Row="1">
                <Track.DecreaseRepeatButton>
                    <!--上页按钮-->
                    <RepeatButton Command="ScrollBar.PageUpCommand" />
                </Track.DecreaseRepeatButton>
                <Track.Thumb>
                    <!--滑块-->
                    <Thumb Background="{DynamicResource VerticalTrackThumbBackgroundBrush}" />
                </Track.Thumb>
                <Track.IncreaseRepeatButton>
                    <!--下页按钮-->
                    <RepeatButton Command="ScrollBar.PageDownCommand" />
                </Track.IncreaseRepeatButton>
            </Track>
            <!--下行按钮-->
            <RepeatButton Grid.Row="2" Command="ScrollBar.LineDownCommand"/>
        </Grid>
    </ControlTemplate>
    <!-- 横向滚动条template  -->
    <ControlTemplate x:Key="HorizontalScrollBar" TargetType="{x:Type RangeBase}">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="auto"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition  Width="auto"/>
            </Grid.ColumnDefinitions>
            <!--左行按钮-->
            <RepeatButton  Command="ScrollBar.LineLeftCommand"/>
            <!--轨道-->
            <Track Name="PART_Track" Grid.Column="1">
                <Track.DecreaseRepeatButton>
                    <!--左页按钮-->
                    <RepeatButton Command="ScrollBar.PageLeftCommand" />
                </Track.DecreaseRepeatButton>
                <Track.Thumb >
                    <!--滑块-->
                    <Thumb Background="{DynamicResource HorizontalTrackThumbBackgroundBrush}" />
                </Track.Thumb>
                <Track.IncreaseRepeatButton>
                    <!--右页按钮-->
                    <RepeatButton Command="ScrollBar.PageRightCommand" />
                </Track.IncreaseRepeatButton>
            </Track>
            <!--右行按钮-->
            <RepeatButton Grid.Column="2" Command="ScrollBar.LineRightCommand"/>
        </Grid>
    </ControlTemplate>
</ResourceDictionary>

2.仿移动端滚动条

https://blog.csdn.net/u013113678/article/details/120811416

3.音量调节滚动条

https://blog.csdn.net/u013113678/article/details/120819414

4.加减按钮滚动条

https://blog.csdn.net/u013113678/article/details/120843370

总结

wpf的ScrollBar具有很强的定制性,尤其是将其分成了6个部分,两个行按钮、两个页按钮、一个滑块、一个轨道。每个部分都可以定义其样式及布局,或者删减。非常好的解决了曾经Windows上滚动条难以修改的痛点。

  • 17
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeOfCC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值