WPF开发分页控件:实现可定制化分页功能及实现原理解析
概要
本文将详细介绍如何使用WPF(Windows Presentation Foundation)开发一个分页控件,并深入解析其实现原理。我们将通过使用XAML和C#代码相结合的方式构建分页控件,并确保它具有高度的可定制性,以便在不同的应用场景中满足各种需求。
一.简介
分页控件是在许多应用程序中常见的一种界面元素,特别是在数据展示的场景中。它允许用户浏览大量数据,并根据需要切换到不同的数据页。
二.需求分析
我们首先来分析一下一个分页控件的基本构成。

2.1 总条目数(TotalItems)
表示总数据量。
2.2 每页条目数(PageSize)
表示每页显示的条目数。
2.3 总页数(PageCount)
表示根据总条目数与每页条目数计算出来的页数。
2.4 分页/页码按钮数量(PageNumberCount)
分页控件中可以点击的页码按钮。
2.5 当前页(CurrentPage)
当前显示的页,通常高亮显示。
三.控件命令和事件
3.1 页面跳转命令(GoToPageCommand)
该命令用于在XAML代码中触发页面跳转操作。
3.2当前页变更事件
当CurrentPage参数改变后触发该事件,通常在该事件中执行数据查询操作。
四.代码实现
通过以上原理分析,我们提取出了分页控件需要包含的基本要素,下面我们通过这些信息来组装成一个分页控件。
1 <Style TargetType="{x:Type local:Pager}">
2 <Setter Property="Template">
3 <Setter.Value>
4 <ControlTemplate TargetType="{x:Type local:Pager}">
5 <Border Background="{TemplateBinding Background}"
6 BorderBrush="{TemplateBinding BorderBrush}"
7 BorderThickness="{TemplateBinding BorderThickness}">
8 <StackPanel Orientation="Horizontal" ClipToBounds="True">
9 <Button Command="{x:Static local:Pager.GoToPageCommand}" CommandParameter="1" Margin="0,0,5,0" Content="首页"></Button>
10 <Button Command="{x:Static local:Pager.GoToPageCommand}" CommandParameter="-" Margin="5,0" Content="上一页"></Button>
11 <ItemsControl ItemsSource="{TemplateBinding PageButtons}">
12 <ItemsControl.ItemsPanel>
13 <ItemsPanelTemplate>
14 <StackPanel Orientation="Horizontal"/>
15 </ItemsPanelTemplate>
16 </ItemsControl.ItemsPanel>
17 <ItemsControl.ItemTemplate>
18 <DataTemplate>
19 <ToggleButton MinWidth="{Binding RelativeSource={RelativeSource Mode=Self},Path=ActualHeight}"
20 Content="{Binding Page}"
21 IsChecked="{Binding IsCurrentPage}"
22 Command="{x:Static local:Pager.GoToPageCommand}"
23 CommandParameter="{Binding Page}"
24 Margin="5,0"/>
25 </DataTemplate>
26 </ItemsControl.ItemTemplate>
27 </ItemsControl>
28 <Button Command="{x:Static local:Pager.GoToPageCommand}" CommandParameter="+" Margin="5,0" Content="下一页"></Button>
29 <Button Command="{x:Static local:Pager.GoToPageCommand}" CommandParameter="尾页" Margin="5,0,0,0" Content="{DynamicResource LastPage}"></Button>
30 </StackPanel>
31 </Border>
32 </ControlTemplate>
33 </Setter.Value>
34 </Setter>
35 </Style>

五.多样化需求
在不同的业务场景下需要的分页控件可能不尽相同,那么如何来满足多样化需求呢,答案就是自定义控件模板。下面演示几种常见的分页控件如何实现。
只需要“上一页”、“下一页”的情况
1 <Style TargetType="{x:Type Controls:Pager}">
2 <Setter Property="Template">
3 <Setter.Value>
4 <ControlTemplate TargetType="{x:Type Controls:Pager}">
5 <Border Background="{TemplateBinding Background}"
6 BorderBrush="{TemplateBinding BorderBrush}"
7 BorderThickness="{TemplateBinding BorderThickness}">
8 <StackPanel Orientation="Horizontal" ClipToBounds="True">
9 <Button Command="{x:Static Controls:Pager.GoToPageCommand}" CommandParameter="-" Margin="5,0" Content="{DynamicResource PreviousPage}"></Button>
10 <Button Command="{x:Static Controls:Pager.GoToPageCommand}" CommandParameter="+" Margin="5,0" Content="{DynamicResource NextPage}"></Button>
11 </StackPanel>
12 </Border>
13 </ControlTemplate>
14 </Setter.Value>
15 </Setter>
16 </Style>

只需要“首页”、“上一页”、“下一页”、“尾页”的情况。
1 <Style TargetType="{x:Type Controls:Pager}">
2 <Setter Property="Template">
3 <Setter.Value>
4 <ControlTemplate TargetType="{x:Type Controls:Pager}">
5 <Border Background="{TemplateBinding Background}"
6 BorderBrush="{TemplateBinding BorderBrush}"
7 BorderThickness="{TemplateBinding BorderThickness}">
8 <StackPanel Orientation="Horizontal" ClipToBounds="True">
9 <Button Command="{x:Static Controls:Pager.GoToPageCommand}" CommandParameter="1" Margin="0,0,5,0" Content="{DynamicResource FirstPage}"></Button>
10 <Button Command="{x:Static Controls:Pager.GoToPageCommand}" CommandParameter="-" Margin="5,0" Content="{DynamicResource PreviousPage}"></Button>
11 <Button Command="{x:Static Controls:Pager.GoToPageCommand}" CommandParameter="+" Margin="5,0" Content="{DynamicResource NextPage}"></Button>
12 <Button Command="{x:Static Controls:Pager.GoToPageCommand}" CommandParameter="{TemplateBinding PageCount}" Margin="5,0,0,0" Content="{DynamicResource LastPage}"></Button>
13 </StackPanel>
14 </Border>
15 </ControlTemplate>
16 </Setter.Value>
17 </Setter>
18 </Style>

数字显示“首页”、“尾页”的情况。
1 <Style TargetType="{x:Type Controls:Pager}">
2 <Setter Property="Template">
3 <Setter.Value>
4 <ControlTemplate TargetType="{x:Type Controls:Pager}">
5 <Border Background="{TemplateBinding Background}"
6 BorderBrush="{TemplateBinding BorderBrush}"
7 BorderThickness="{TemplateBinding BorderThickness}">
8 <StackPanel Orientation="Horizontal" ClipToBounds="True">
9 <Button Command="{x:Static Controls:Pager.GoToPageCommand}"
10 CommandParameter="1"
11 Content="1"
12 MinWidth="{Binding RelativeSource={RelativeSource Mode=Self},Path=ActualHeight}"
13 Margin="0,0,5,0">
14 <Button.Visibility>
15 <MultiBinding Converter="{StaticResource PageNumberToVisibilityConverter}" ConverterParameter="First">
16 <Binding RelativeSource="{RelativeSource AncestorType=Controls:Pager}" Path="CurrentPage"/>
17 <Binding RelativeSource="{RelativeSource AncestorType=Controls:Pager}" Path="PageNumberCount"/>
18 <Binding RelativeSource="{RelativeSource AncestorType=Controls:Pager}" Path="PageCount"/>
19 </MultiBinding>
20 </Button.Visibility>
21 </Button>
22 <Button IsEnabled="False" Margin="5,0" MinWidth="{Binding RelativeSource={RelativeSource Mode=Self},Path=ActualHeight}" Content="...">
23 <Button.Visibility>
24 <MultiBinding Converter="{StaticResource PageNumberToVisibilityConverter}" ConverterParameter="First">
25 <Binding RelativeSource="{RelativeSource AncestorType=Controls:Pager}" Path="CurrentPage"/>
26 <Binding RelativeSource="{RelativeSource AncestorType=Controls:Pager}" Path="PageNumberCount"/>
27 <Binding RelativeSource="{RelativeSource AncestorType=Controls:Pager}" Path="PageCount"/>
28 </MultiBinding>
29 </Button.Visibility>
30 </Button>
31 <Button Command="{x:Static Controls:Pager.GoToPageCommand}" CommandParameter="-" Margin="5,0" Content="{DynamicResource PreviousPage}"></Button>
32 <ItemsControl ItemsSource="{TemplateBinding PageButtons}">
33 <ItemsControl.ItemsPanel>
34 <ItemsPanelTemplate>
35 <StackPanel Orientation="Horizontal"/>
36 </ItemsPanelTemplate>
37 </ItemsControl.ItemsPanel>
38 <ItemsControl.ItemTemplate>
39 <DataTemplate>
40 <ToggleButton MinWidth="{Binding RelativeSource={RelativeSource Mode=Self},Path=ActualHeight}"
41 Content="{Binding Page}"
42 Margin="5,0"
43 IsChecked="{Binding IsCurrentPage}"
44 Command="{x:Static Controls:Pager.GoToPageCommand}"
45 CommandParameter="{Binding Page}"/>
46 </DataTemplate>
47 </ItemsControl.ItemTemplate>
48 </ItemsControl>
49 <Button Command="{x:Static Controls:Pager.GoToPageCommand}" CommandParameter="+" Margin="5,0" Content="{DynamicResource NextPage}"></Button>
50 <Button IsEnabled="False" Margin="5,0" MinWidth="{Binding RelativeSource={RelativeSource Mode=Self},Path=ActualHeight}" Content="...">
51 <Button.Visibility>
52 <MultiBinding Converter="{StaticResource PageNumberToVisibilityConverter}">
53 <Binding RelativeSource="{RelativeSource AncestorType=Controls:Pager}" Path="CurrentPage"/>
54 <Binding RelativeSource="{RelativeSource AncestorType=Controls:Pager}" Path="PageNumberCount"/>
55 <Binding RelativeSource="{RelativeSource AncestorType=Controls:Pager}" Path="PageCount"/>
56 </MultiBinding>
57 </Button.Visibility>
58 </Button>
59 <Button Command="{x:Static Controls:Pager.GoToPageCommand}"
60 CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Controls:Pager},Path=PageCount}"
61 Content="{Binding RelativeSource={RelativeSource AncestorType=Controls:Pager},Path=PageCount}"
62 MinWidth="{Binding RelativeSource={RelativeSource Mode=Self},Path=ActualHeight}"
63 Margin="5,0,0,0">
64 <Button.Visibility>
65 <MultiBinding Converter="{StaticResource PageNumberToVisibilityConverter}">
66 <Binding RelativeSource="{RelativeSource AncestorType=Controls:Pager}" Path="CurrentPage"/>
67 <Binding RelativeSource="{RelativeSource AncestorType=Controls:Pager}" Path="PageNumberCount"/>
68 <Binding RelativeSource="{RelativeSource AncestorType=Controls:Pager}" Path="PageCount"/>
69 </MultiBinding>
70 </Button.Visibility>
71 </Button>
72
73 <StackPanel Orientation="Horizontal" Margin="5,0,0,0">
74 <TextBlock Text="转到" VerticalAlignment="Center"/>
75 <TextBox x:Name="tbox_Page" Width="40" Margin="5,0" Padding="5" HorizontalContentAlignment="Center" VerticalAlignment="Center"/>
76 <TextBlock Text="页" VerticalAlignment="Center"/>
77 <Button Margin="5,0,0,0" Command="{x:Static Controls:Pager.GoToPageCommand}" CommandParameter="{Binding ElementName=tbox_Page,Path=Text}">确定</Button>
78 </StackPanel>
79 </StackPanel>
80 </Border>
81 </ControlTemplate>
82 </Setter.Value>
83 </Setter>
84 </Style>

可以调整每页显示条目,可以显示总页数,可以跳转到指定页的情况。
1 <Style TargetType="{x:Type Controls:Pager}">
2 <Setter Property="Template">
3 <Setter.Value>
4 <ControlTemplate TargetType="{x:Type Controls:Pager}">
5 <Border Background="{TemplateBinding Background}"
6 BorderBrush="{TemplateBinding BorderBrush}"
7 BorderThickness="{TemplateBinding BorderThickness}">
8 <StackPanel Orientation="Horizontal" ClipToBounds="True">
9 <Button Command="{x:Static Controls:Pager.GoToPageCommand}" CommandParameter="1" Margin="0,0,5,0" MinWidth="{Binding RelativeSource={RelativeSource Mode=Self},Path=ActualHeight}" Content="{DynamicResource FirstPage}"></Button>
10 <Button Command="{x:Static Controls:Pager.GoToPageCommand}" CommandParameter="-" Margin="5,0" MinWidth="{Binding RelativeSource={RelativeSource Mode=Self},Path=ActualHeight}" Content="{DynamicResource PreviousPage}"></Button>
11 <ItemsControl ItemsSource="{TemplateBinding PageButtons}">
12 <ItemsControl.ItemsPanel>
13 <ItemsPanelTemplate>
14 <StackPanel Orientation="Horizontal"/>
15 </ItemsPanelTemplate>
16 </ItemsControl.ItemsPanel>
17 <ItemsControl.ItemTemplate>
18 <DataTemplate>
19 <ToggleButton MinWidth="{Binding RelativeSource={RelativeSource Mode=Self},Path=ActualHeight}"
20 Content="{Binding Page}"
21 Margin="5,0"
22 IsChecked="{Binding IsCurrentPage}"
23 Command="{x:Static Controls:Pager.GoToPageCommand}"
24 CommandParameter="{Binding Page}"/>
25 </DataTemplate>
26 </ItemsControl.ItemTemplate>
27 </ItemsControl>
28 <Button Command="{x:Static Controls:Pager.GoToPageCommand}" CommandParameter="+" Margin="5,0" MinWidth="{Binding RelativeSource={RelativeSource Mode=Self},Path=ActualHeight}" Content="{DynamicResource NextPage}"></Button>
29 <Button Command="{x:Static Controls:Pager.GoToPageCommand}" CommandParameter="{TemplateBinding PageCount}" Margin="5,0,0,0" MinWidth="{Binding RelativeSource={RelativeSource Mode=Self},Path=ActualHeight}" Content="{DynamicResource LastPage}"></Button>
30 <StackPanel Orientation="Horizontal" Margin="5,0,0,0">
31 <TextBlock Margin="0,0,5,0" Text="每页" VerticalAlignment="Center"/>
32 <ComboBox Margin="5,0" SelectedIndex="0" VerticalContentAlignment="Center" SelectedItem="{Binding RelativeSource={RelativeSource AncestorType=Controls:Pager},Path=PageSize,Mode=OneWayToSource}">
33 <sys:Int32>5</sys:Int32>
34 <sys:Int32>10</sys:Int32>
35 <sys:Int32>15</sys:Int32>
36 <sys:Int32>20</sys:Int32>
37 </ComboBox>
38 <TextBlock Text="条" VerticalAlignment="Center" Margin="5,0"/>
39 <TextBlock VerticalAlignment="Center" Margin="5,0">
40 <Run Text="共"/>
41 <Run Text="{Binding RelativeSource={RelativeSource AncestorType=Controls:Pager},Path=PageCount}"/>
42 <Run Text="页"/>
43 </TextBlock>
44 <TextBlock Text="转到" VerticalAlignment="Center"/>
45 <TextBox x:Name="tbox_Page" Width="40" Margin="5,0" Padding="5" HorizontalContentAlignment="Center" VerticalAlignment="Center"/>
46 <TextBlock Text="页" VerticalAlignment="Center"/>
47 <Button Margin="5,0,0,0" Command="{x:Static Controls:Pager.GoToPageCommand}" CommandParameter="{Binding ElementName=tbox_Page,Path=Text}">确定</Button>
48 </StackPanel>
49 </StackPanel>
50 </Border>
51 </ControlTemplate>
52 </Setter.Value>
53 </Setter>
54 </Style>

除了修改模板实现不同的形态的分页控件以外,还可以用图标替换掉“首页”、“上一页”、“下一页”、”尾页”等文字。

六.个性化控件外观
项目中的界面外观可能多种多样,有自己写的控件样式,也有使用第三方UI库的样式,如何跟它们搭配使用呢。
自定义控件样式
1 <Style TargetType="Button">
2 <Setter Property="Padding" Value="5"/>
3 <Setter Property="Background" Value="Red"/>
4 </Style>
5 <Style TargetType="ToggleButton">
6 <Setter Property="Padding" Value="5"/>
7 <Setter Property="Background" Value="Red"/>
8 </Style>

使用第三方UI库
1.HandyControl
1 <ResourceDictionary>
2 <ResourceDictionary.MergedDictionaries>
3 <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml" />
4 <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml" />
5 </ResourceDictionary.MergedDictionaries>
6 </ResourceDictionary>

2.MaterialDesign
1 <ResourceDictionary>
2 <ResourceDictionary.MergedDictionaries>
3 <materialDesign:CustomColorTheme BaseTheme="Light" PrimaryColor="#FF3561FF" SecondaryColor="#FF3561FF" />
4 <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
5 </ResourceDictionary.MergedDictionaries>
6 </ResourceDictionary>

WPF开发分页控件:实现可定制化分页功能及实现原理解析的更多相关文章
- 【WPF】WPF开发用户控件、用户控件属性依赖DependencyProperty实现双向绑定、以及自定义实现Command双向绑定功能演示
前言: Wpf开发过程中,最经常使用的功能之一,就是用户控件(UserControl)了.用户控件可以用于开发用户自己的控件进行使用,甚至可以用于打造一套属于自己的UI框架.依赖属性(Dependen ...
- Web用户控件开发--分页控件
分页是Web应用程序中最常用到的功能之一,在ASP.NET中,虽然自带了一些可以分页的数据控件,但其分页功能并不尽如人意.本文对于这些数据控件的假分页暂且不表,如有不明白的同学请百Google度之. ...
- 在DevExpress程序中使用Winform分页控件直接录入数据并保存
一般情况下,我们都倾向于使用一个组织比较好的独立界面来录入或者展示相关的数据,这样处理比较规范,也方便显示比较复杂的数据.不过在一些情况下,我们也可能需要直接在GridView表格上直接录入或者修改数 ...
- 自己动手用Javascript写一个无刷新分页控件
.NET技术交流群:337901356 ,欢迎您的加入! 对 于一个用户体验好的网站来说,无刷新技术是很重要的,无刷新,顾名思义,就是局部刷新数据,有用过Asp.net Web Form技术开发网页的 ...
- sharepoint 2010 列表数据分页控件介绍 pagination UserControl
转:http://blog.csdn.net/chenxinxian/article/details/8714391 这里主要是介绍下最近开发的一个sharepoint列表或者文档库的分页控件,并且把 ...
- 开发框架模块视频系列(2)-Winform分页控件介绍
在软件开发过程中,为了节省开发时间,提高开发效率,统一用户处理界面,尽可能使用成熟.功能强大的分页控件,这款Winform环境下的分页控件,集成了数据分页.内容提示.数据打印.数据导出.表头中文转义等 ...
- asp.net分页控件
一.说明 AspNetPager.dll这个分页控件主要用于asp.net webform网站,现将整理代码如下 二.代码 1.首先在测试页面Default.aspx页面添加引用 <%@ Reg ...
- 如何Windows分页控件中增加统计功能
在我的博客里面,很多Winform程序里面都用到了分页处理,这样可以不管是在直接访问数据库的场景还是使用网络方式访问WCF服务获取数据,都能获得较好的效率,因此WInform程序里面的分页控件的使用是 ...
- 小白写的一个ASP.NET分页控件,仅供娱乐
无聊,第一次写博客,自己动手写了一个分页控件.由于我是新手,有很多地方写得不够好,希望各位大牛多多指正.哈哈哈 /// <summary> /// 分页控件 /// </summar ...
- WPF 分页控件 WPF 多线程 BackgroundWorker
WPF 分页控件 WPF 多线程 BackgroundWorker 大家好,好久没有发表一篇像样的博客了,最近的开发实在头疼,很多东西无从下口,需求没完没了,更要命的是公司的开发从来不走正规流程啊, ...
随机推荐
- 我的小程序之旅九:微信开放平台unionId机制介绍
一.机制说明 参考文档:https://developers.weixin.qq.com/minigame/dev/guide/open-ability/union-id.html 如果开发者拥有多个 ...
- JetBrains全系列软件激活教程激活码以及JetBrains系列软件汉化包
最新激活方式 如果安装过无限试用.修改过 hosts 请先卸载干净旧版本再安装,否需无法激活! 以 WebStorm 为例 JetBrains官网 https://www.jetbrains.com/ ...
- 海康摄像SDK开发笔记(一):海康威视网络摄像头SDK介绍与模块功能
前言 视频监控.人脸识别等应用中经常使用到摄像头,当前占据主流视频监控摄像头就是海康和大华两家,都可通过自家的sdk或者是onvif方式使用和控制摄像头. 本文章讲解海康的sdk方式. 海康 ...
- Ubuntu防火墙相关
查看防火墙当前状态 sudo ufw status 开启防火墙 sudo ufw enable 关闭防火墙 sudo ufw disable 查看防火墙版本 sudo ufw version 默认允许 ...
- Html飞机大战(十四): 分数编辑和生命值设定
好家伙,这章让我感受到了面向对象的优势了 1.分数设置 每个种类的敌机分数都设置好了, 那么当我们击毁不同的敌机后,加上不同的分数就行了 但是我们还是要想一下, 我要在哪里放这个分数增加的方法 ...
- 【Azure 云服务】Azure Cloud Service如何来设置固定IP地址(ReservedIP)
问题描述 在云中环境,部署的应用到云服务(Cloud Service)都是动态的IP地址,所以在添加DNS记录的时候,都是使用CNAME,但如果需要在DNS中添加A记录,则需要一个固定IP. 解决方案 ...
- 【Azure Redis 缓存】Azure Cache for Redis 如何迁移
Azure Cache for Redis 如何迁移 [Azure Redis 缓存]Azure Cache for Redis有默认备份可以用于恢复么?一文中,介绍了使用RDB文件的方式来迁移Red ...
- 面试官上来就让手撕HashMap的7种遍历方式,当场愣住,最后只写出了3种
写在开头 今天有个小伙伴私信诉苦,说面试官上来就让他手撕HashMap的7种遍历方式,最终只写出3种常用的,怀疑面试官是在故意***难.这个问题大家怎么看? 反正我个人感觉这肯定不是***难,&quo ...
- linux基本知识汇总1(基础命令) 20000字汇总
$$$$ 命令选项查看方式1.内建命令(help)格式: help + 内建命令#### help 命令 // 命令使用说明 2.外部命令(–help)一般是 Linux 命令自带的帮助信息,并不是所 ...
- 这波操作看麻了!十亿行数据,从71s到1.7s的优化之路。
你好呀,我是歪歪. 春节期间关注到了一个关于 Java 方面的比赛,很有意思.由于是开源的,我把项目拉下来试图学(白)习(嫖)别人的做题思路,在这期间一度让我产生了一个自我怀疑: 他们写的 Java ...