WPF 自定义ScrollViwer
ScrollViewer自定义样式
ScrollViewer在各种列表、集合控件中广泛使用的基础组建,先看看效果图:

如上图,ScrollViewer简单来说分两部分,一个横向的滚动条,一个垂直滚动条,两个样式、模板、功能都基本一样,他们都是ScrollBar。以垂直滚动条为例,分解一下,分解图:

- 1:向上滑动的按钮,用RepeatButton实现功能;
- 2:上部分滑块,功能同1,也是一个RepeatButton来实现的;
- 3:中间可拖动滑块,用一个Thumb来实现;
- 4:下部分滑块,和5功能一样,向下滑动,用一个RepeatButton来实现;
- 5:向下滑动的按钮,用RepeatButton实现功能;
上面实现的是一个标准的垂直滑动条ScrollBar组成,实际可用根据需求定制,实现不同效果的滑动效果。以上各部分的样式代码:
<Style x:Key="ScrollBarButton" TargetType="{x:Type RepeatButton}">
        <Setter Property="Background" Value="Transparent"></Setter>
        <Setter Property="Foreground" Value="{StaticResource TextForeground}"></Setter>
        <Setter Property="VerticalAlignment" Value="Center"></Setter>
        <Setter Property="HorizontalAlignment" Value="Center"></Setter>
        <Setter Property="Width" Value="auto"></Setter>
        <Setter Property="Height" Value="auto"></Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type RepeatButton}">
                    <TextBlock x:Name="FIcon" FontSize="12" Text="{TemplateBinding local:ControlAttachProperty.FIcon}" Margin="1"
                               Style="{StaticResource FIcon}" />
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Foreground" Value="{StaticResource MouseOverForeground}" TargetName="FIcon"/>
                        </Trigger>
                        <Trigger Property="IsPressed" Value="True">
                            <Setter Property="Foreground" Value="{StaticResource PressedForeground}" TargetName="FIcon"/>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Opacity" Value="0.5" TargetName="FIcon"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <!--滚动条滑块两边按钮样式-->
    <Style x:Key="ScrollBarTrackButton" TargetType="{x:Type RepeatButton}">
        <Setter Property="Background" Value="Transparent"></Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type RepeatButton}">
                    <Border Background="Transparent"></Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <!--滚动条滑块样式-->
    <ControlTemplate x:Key="ThumbTemplate" TargetType="Thumb">
        <Grid>
            <Border  x:Name="Bg" CornerRadius="4" Margin="2" SnapsToDevicePixels="True" Background="{StaticResource ScrollBarForeround}">
                <!--<Border.Background>
                    <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                        <GradientStop Color="#C7C0C0" Offset="0.15"/>
                        <GradientStop Color="#AFA9A9" Offset=".5"/>
                        <GradientStop Color="#989494" Offset=".5"/>
                        <GradientStop Color="#858585" Offset="1"/>
                    </LinearGradientBrush>
                </Border.Background>-->
            </Border>
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Background" Value="{StaticResource MouseOverForeground}" TargetName="Bg"></Setter>
            </Trigger>
            <Trigger Property="IsEnabled" Value="False">
                <Setter Property="Opacity" Value="0.5" TargetName="Bg"></Setter>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
    <!--水平滚滚动条模板-->
    <ControlTemplate x:Key="HorizontalScrollBar" TargetType="{x:Type ScrollBar}">
        <Grid x:Name="HorizontalRoot" Height="{TemplateBinding Height}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <!--外部背景,好像不用更好看-->
            <!--<Border x:Name="Bg" Grid.Column="0" Grid.ColumnSpan="3" CornerRadius="0"  Opacity="0" Background="#858585"/>-->
            <!--内部背景-->
            <Border x:Name="BgInner" Grid.Column="1" Margin="0" SnapsToDevicePixels="True" Opacity="0.3"  CornerRadius="6" Background="{StaticResource ScrollBarBackground}"/>
            <!--左按钮-->
            <Border Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center">
                <RepeatButton  local:ControlAttachProperty.FIcon=""  Style="{StaticResource ScrollBarButton}" x:Name="HorizontalSmallDecrease"
                                 IsTabStop="False" Interval="50" Margin="0,1,0,0" Command="ScrollBar.LineLeftCommand"/>
            </Border>
            <!--中间滑动区域-->
            <Track x:Name="PART_Track" IsDirectionReversed="False" Grid.Column="1">
                <!--左滑块-->
                <Track.DecreaseRepeatButton>
                    <RepeatButton x:Name="HorizontalLargeDecrease" Command="ScrollBar.PageLeftCommand"
                                      IsTabStop="False" Interval="50" Style="{DynamicResource ScrollBarTrackButton}" />
                </Track.DecreaseRepeatButton>
                <!--中间滑块 Margin="1" VerticalAlignment="Center" VerticalContentAlignment="Center" -->
                <Track.Thumb>
                    <Thumb Template="{StaticResource ThumbTemplate}" />
                </Track.Thumb>
                <!--右滑块-->
                <Track.IncreaseRepeatButton>
                    <RepeatButton x:Name="HorizontalLargeIncrease" Command="ScrollBar.PageRightCommand"
                                      IsTabStop="False"  Interval="50" Style="{DynamicResource ScrollBarTrackButton}" />
                </Track.IncreaseRepeatButton>
            </Track>
            <!--右按钮-->
            <Border Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center">
                <RepeatButton local:ControlAttachProperty.FIcon=""  Style="{StaticResource ScrollBarButton}"
                                 IsTabStop="False" Interval="50" Margin="0,1,0,0" Command="ScrollBar.LineRightCommand"/>
            </Border>
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="IsMouseOver" Value="true">
                <Setter TargetName="BgInner" Property="Opacity" Value="0.5"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
    <!--垂直滚滚动条模板-->
    <ControlTemplate x:Key="VerticalScrollBar" TargetType="{x:Type ScrollBar}">
        <Grid x:Name="VerticalRoot" Height="{TemplateBinding Height}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <!--外部背景,好像不用更好看-->
            <!--<Border x:Name="Bg" Grid.Row="0" Grid.RowSpan="3" CornerRadius="0" Opacity="0" Background="#858585"/>-->
            <!--内部背景-->
            <Border x:Name="BgInner" Grid.Row="1" Margin="0" CornerRadius="6" SnapsToDevicePixels ="True" Opacity="0.3"  Background="{StaticResource ScrollBarBackground}"/>
            <!--上按钮-->
            <Border Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center" x:Name="VerticalSmallDecrease">
                <RepeatButton local:ControlAttachProperty.FIcon=""  Style="{StaticResource ScrollBarButton}"
                                 IsTabStop="False" Interval="50" Margin="0" Command="ScrollBar.LineUpCommand"/>
            </Border>
            <!--中间滑动区域-->
            <Track x:Name="PART_Track" IsDirectionReversed="true" Grid.Row="1">
                <!--上滑块-->
                <Track.DecreaseRepeatButton>
                    <RepeatButton x:Name="HorizontalLargeDecrease" Command="ScrollBar.PageUpCommand"
                                      IsTabStop="False" Interval="50" Style="{DynamicResource ScrollBarTrackButton}" />
                </Track.DecreaseRepeatButton>
                <!--中间滑块-->
                <Track.Thumb>
                    <Thumb Template="{StaticResource ThumbTemplate}" MinHeight="10"/>
                </Track.Thumb>
                <!--下滑块-->
                <Track.IncreaseRepeatButton>
                    <RepeatButton x:Name="HorizontalLargeIncrease" Command="ScrollBar.PageDownCommand"
                                      IsTabStop="False" Interval="50" Style="{DynamicResource ScrollBarTrackButton}" />
                </Track.IncreaseRepeatButton>
            </Track>
            <!--下按钮-->
            <Border Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Center" x:Name="VerticalSmallIncrease">
                <RepeatButton local:ControlAttachProperty.FIcon=""  Style="{StaticResource ScrollBarButton}"
                                 IsTabStop="False" Interval="50" Margin="0" Command="ScrollBar.LineDownCommand"/>
            </Border>
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="IsMouseOver" Value="true">
                <Setter TargetName="BgInner" Property="Opacity" Value="0.5"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
    <!--ScrollBar样式-->
    <Style x:Key="DefaultScrollBar" TargetType="{x:Type ScrollBar}">
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <Setter Property="OverridesDefaultStyle" Value="true" />
        <Style.Triggers>
            <Trigger Property="Orientation" Value="Horizontal">
                <Setter Property="Template" Value="{StaticResource HorizontalScrollBar}" />
                <Setter Property="Height" Value="{StaticResource ScrollBarSize}" />
            </Trigger>
            <Trigger Property="Orientation" Value="Vertical">
                <Setter Property="Template" Value="{StaticResource VerticalScrollBar}" />
                <Setter Property="Width" Value="{StaticResource ScrollBarSize}" />
            </Trigger>
        </Style.Triggers>
    </Style>
<!--ScrollViewer样式-->
<Style x:Key="DefaultScrollViewer" TargetType="{x:Type ScrollViewer}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid x:Name="Grid" Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" x:Name="leftColumn" />
<ColumnDefinition Width="Auto" x:Name="rightColumn" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}"
CanHorizontallyScroll="False" CanVerticallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}" Margin="{TemplateBinding Padding}"
Grid.Row="0" Grid.Column="0" />
<!--垂直滚动条 -->
<ScrollBar x:Name="PART_VerticalScrollBar" AutomationProperties.AutomationId="VerticalScrollBar"
ViewportSize="{TemplateBinding ViewportHeight}"
Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}"
Minimum="0" Grid.Row="0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>
<!--水平底部滚动条-->
<ScrollBar x:Name="PART_HorizontalScrollBar" AutomationProperties.AutomationId="HorizontalScrollBar"
Cursor="Arrow" Grid.Column="0" Maximum="{TemplateBinding ScrollableWidth}"
Minimum="0" Orientation="Horizontal" Grid.Row="1"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
ViewportSize="{TemplateBinding ViewportWidth}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
使用很简单,如果想通用,把上面定义的ScrollViewer设置为默认样式即可:
<Style TargetType="{x:Type ScrollBar}" BasedOn="{StaticResource DefaultScrollBar}"></Style>
<Style TargetType="{x:Type ScrollViewer}" BasedOn="{StaticResource DefaultScrollViewer}"></Style>
WPF 自定义ScrollViwer的更多相关文章
- WPF 自定义柱状图 BarChart
		WPF 自定义柱状图 当前的Telerik控件.DevExpress控件在图表控件方面做得不错,但是有时项目中需要特定的样式,不是只通过修改图表的模板和样式就能实现的. 或者说,通过修改当前的第三方控 ... 
- wpf 自定义圆形按钮
		wpf 自定义圆形按钮 效果图 默认样式 获取焦点样式 点击样式 下面是实现代码: 一个是自定义控件类,一个是控件类皮肤 using System; using System.Collections. ... 
- WPF自定义窗口基类
		WPF自定义窗口基类时,窗口基类只定义.cs文件,xaml文件不定义.继承自定义窗口的类xaml文件的根节点就不再是<Window>,而是自定义窗口类名(若自定义窗口与继承者不在同一个命名 ... 
- WPF 自定义 MessageBox (相对完善版)
		WPF 自定义 MessageBox (相对完善版) 基于WPF的自定义 MessageBox. 众所周知WPF界面美观.大多数WPF元素都可以简单的修改其样式,从而达到程序的风格统一.可是当 ... 
- WPF自定义Window样式(2)
		1. 引言 在上一篇中,介绍了如何建立自定义窗体.接下来,我们需要考虑将该自定义窗体基类放到类库中去,只有放到类库中,我们才能在其他地方去方便的引用该基类. 2. 创建类库 接上一篇的项目,先添加一个 ... 
- WPF自定义Window样式(1)
		1. 引言 WPF是制作界面的一大利器.最近在做一个项目,用的就是WPF.既然使用了WPF了,那么理所当然的,需要自定义窗体样式.所使用的代码是在网上查到的,遗憾的是,整理完毕后,再找那篇帖子却怎么也 ... 
- WPF自学入门(九)WPF自定义窗口基类
		今天简单记录一个知识点:WPF自定义窗口基类,常用winform的人知道,winform的窗体继承是很好用的,写一个基础窗体,直接在后台代码改写继承窗体名.但如果是WPF要继承窗体,我个人感觉没有理解 ... 
- WPF自定义TabControl样式
		WPF自定义TabControl,TabControl美化 XAML代码: <TabControl x:Class="SunCreate.Common.Controls.TabCont ... 
- WPF 自定义ComboBox样式,自定义多选控件
		原文:WPF 自定义ComboBox样式,自定义多选控件 一.ComboBox基本样式 ComboBox有两种状态,可编辑和不可编辑状态.通过设置IsEditable属性可以切换控件状态. 先看基本样 ... 
随机推荐
- jsp int转String or String转int 方法
			将字串 String 转换成整数 int? A. 有两个方法: 1). int i = Integer.parseInt([String]); 或 i = Integer.parseInt([St ... 
- 日笔记--C# 从数据库取表格到DataGridView---json传输
			只作为个人学习笔记. class OpData { // 创建一个和客户端通信的套接字 Socket socketwatch = null; //连接Access字符串 string strCon; ... 
- JS 浏览器对象
			1.window对象 1.1 window对象 window对象是BOM的核心.window对象指当前的浏览器窗口 所有JavaScript全局对象 .函数以及变量均自动成为window对象的成员 全 ... 
- python网络编程--管道,信号量,Event,进程池,回调函数
			1.管道 加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行任务修改,即串行修改,速度慢了,但牺牲了速度却保证了数据安全. 文件共享数据实现进程间的通信,但问题是: 1.效率低(共享 ... 
- “全栈2019”Java第一百零八章:匿名内部类与final关键字
			难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ... 
- python2 中 unicode 和 str 之间的转换及与python3 str 的区别
			在python2中字符串分为unicode 和 str 类型 Str To Unicode 使用decode(), 解码 Unicode To Str 使用encode(), 编码 返回数据给前端时需 ... 
- 护网杯圆满结束,还不满足?不如来看看大佬的WP扩展思路~
			护网杯预选赛 WP转载自:https://qingchenldl.github.io/2018/10/13/%E6%8A%A4%E7%BD%91%E6%9D%AFWP-BitPwn/#more WEB ... 
- input disabled的情况下在IOS设备中怎么修改颜色
			-webkit-text-fill-color:black; -webkit-opacity:1; opacity: 1; 一句代码就欧了 
- jvm字节码简介
			1.概述 java虚拟机的指令由一个字节长度的.代表着某种特定操作含义的数字(成为操作码,Opcde)和跟随其后的0到多个此操作所需参数(操作数,Operands).由于操作码的长度为一个字节,所以指 ... 
- oracle中将number类型毫秒值转为时间类型
			在搞数据库时,发现有这样的一个字段,类型是NUMBER(38),查看了一下里面的数据,都是这样的: 13239576781141321326994295132212930680413221297162 ... 
