WPF 实现 DataGrid/ListView 分页控件
在WPF中,通常会选用DataGrid/ListView进行数据展示,如果数据量不多,可以直接一个页面显示出来。如果数据量很大,2000条数据,一次性显示在一个页面中,不仅消耗资源,而且用户体验也很糟糕。这篇博客将介绍如何创建一个分页控件。
为了简单起见,这个分页控件目前只有 首页/上一页/下一页/末页/总页数/第几页 等功能。实现思路,首页/上一页/下一页/末页 这四个通过路由事件来实现,在使用时可以使用命令进行绑定,或者直接使用均可。总页数和第几页通过依赖属性来实现,使用时将页数进行绑定显示即可。示例代码如下:
Pager控件:
<UserControl.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Width" Value="22"/>
<Setter Property="Height" Value="22"/>
</Style>
</UserControl.Resources>
<Grid>
<StackPanel Orientation="Horizontal">
<Button x:Name="FirstPageButton" Margin="5,0" Click="FirstPageButton_Click">
<Path Width="7" Height="10" Data="M0,0L0,10 M0,5L6,2 6,8 0,5" Stroke="Black" StrokeThickness="1" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Button>
<Button x:Name="PreviousPageButton" Margin="0,0,5,0" Click="PreviousPageButton_Click">
<Path Width="8" Height="8" Data="M0,4L8,0 8,8z" Stroke="Black" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Button>
<TextBlock VerticalAlignment="Center">
<Run Text="第"/>
<Run x:Name="rCurrent" Text="0"/>
<Run Text="页"/>
</TextBlock>
<Button Margin="5,0" x:Name="NextPageButton" Click="NextPageButton_Click">
<Path Width="8" Height="8" Data="M0,4L8,0 8,8z" Stroke="Black" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center">
<Path.RenderTransform>
<RotateTransform Angle="180" CenterX="4" CenterY="4" />
</Path.RenderTransform>
</Path>
</Button>
<Button Margin="0,0,5,0" x:Name="LastPageButton" Click="LastPageButton_Click">
<Path x:Name="MainPath" Width="7" Height="10" Data="M0,0L0,10 M0,5 L6,2 6,8 0,5" Stroke="Black" StrokeThickness="1" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center">
<Path.RenderTransform>
<RotateTransform Angle="180" CenterX="3" CenterY="5" />
</Path.RenderTransform>
</Path>
</Button>
<TextBlock VerticalAlignment="Center">
<Run Text="共"/>
<Run x:Name="rTotal" Text="0"/>
<Run Text="页"/>
</TextBlock>
</StackPanel>
</Grid>
C#:
public partial class Pager : UserControl
{
public static RoutedEvent FirstPageEvent;
public static RoutedEvent PreviousPageEvent;
public static RoutedEvent NextPageEvent;
public static RoutedEvent LastPageEvent; public static readonly DependencyProperty CurrentPageProperty;
public static readonly DependencyProperty TotalPageProperty; public string CurrentPage
{
get { return (string)GetValue(CurrentPageProperty); }
set { SetValue(CurrentPageProperty, value); }
} public string TotalPage
{
get { return (string)GetValue(TotalPageProperty); }
set { SetValue(TotalPageProperty, value); }
} public Pager()
{
InitializeComponent();
} static Pager()
{
FirstPageEvent = EventManager.RegisterRoutedEvent("FirstPage", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(Pager));
PreviousPageEvent = EventManager.RegisterRoutedEvent("PreviousPage", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(Pager));
NextPageEvent = EventManager.RegisterRoutedEvent("NextPage", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(Pager));
LastPageEvent = EventManager.RegisterRoutedEvent("LastPage", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(Pager)); CurrentPageProperty = DependencyProperty.Register("CurrentPage", typeof(string), typeof(Pager), new PropertyMetadata(string.Empty,new PropertyChangedCallback(OnCurrentPageChanged)));
TotalPageProperty = DependencyProperty.Register("TotalPage", typeof(string), typeof(Pager), new PropertyMetadata(string.Empty,new PropertyChangedCallback(OnTotalPageChanged)));
} public event RoutedEventHandler FirstPage
{
add { AddHandler(FirstPageEvent, value); }
remove { RemoveHandler(FirstPageEvent, value); }
} public event RoutedEventHandler PreviousPage
{
add { AddHandler(PreviousPageEvent, value); }
remove { RemoveHandler(PreviousPageEvent, value); }
} public event RoutedEventHandler NextPage
{
add { AddHandler(NextPageEvent, value); }
remove { RemoveHandler(NextPageEvent, value); }
} public event RoutedEventHandler LastPage
{
add { AddHandler(LastPageEvent, value); }
remove { RemoveHandler(LastPageEvent, value); }
} public static void OnTotalPageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Pager p = d as Pager; if(p != null)
{
Run rTotal = (Run)p.FindName("rTotal"); rTotal.Text = (string)e.NewValue;
}
} private static void OnCurrentPageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Pager p = d as Pager; if(p != null)
{
Run rCurrrent = (Run)p.FindName("rCurrent"); rCurrrent.Text = (string)e.NewValue;
}
} private void FirstPageButton_Click(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(FirstPageEvent, this));
} private void PreviousPageButton_Click(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(PreviousPageEvent, this));
} private void NextPageButton_Click(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(NextPageEvent, this));
} private void LastPageButton_Click(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(LastPageEvent, this));
}
}
在MainWindow中,
XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions> <DataGrid Grid.Row="0" ItemsSource="{Binding FakeSource}" AutoGenerateColumns="False" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Item Id" Binding="{Binding Id}" Width="80"/>
<DataGridTextColumn Header="Item Name" Binding="{Binding ItemName}" Width="180"/>
</DataGrid.Columns>
</DataGrid> <local:Pager TotalPage="{Binding TotalPage}"
CurrentPage="{Binding CurrentPage, Mode=TwoWay}"
HorizontalAlignment="Center"
Grid.Row="1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="FirstPage">
<i:InvokeCommandAction Command="{Binding FirstPageCommand}" />
</i:EventTrigger>
<i:EventTrigger EventName="PreviousPage">
<i:InvokeCommandAction Command="{Binding PreviousPageCommand}"/>
</i:EventTrigger>
<i:EventTrigger EventName="NextPage">
<i:InvokeCommandAction Command="{Binding NextPageCommand}" />
</i:EventTrigger>
<i:EventTrigger EventName="LastPage">
<i:InvokeCommandAction Command="{Binding LastPageCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</local:Pager>
</Grid>
MainViewModel类:
public class MainViewModel : ViewModel
{
private ICommand _firstPageCommand; public ICommand FirstPageCommand
{
get
{
return _firstPageCommand;
} set
{
_firstPageCommand = value;
}
} private ICommand _previousPageCommand; public ICommand PreviousPageCommand
{
get
{
return _previousPageCommand;
} set
{
_previousPageCommand = value;
}
} private ICommand _nextPageCommand; public ICommand NextPageCommand
{
get
{
return _nextPageCommand;
} set
{
_nextPageCommand = value;
}
} private ICommand _lastPageCommand; public ICommand LastPageCommand
{
get
{
return _lastPageCommand;
} set
{
_lastPageCommand = value;
}
} private int _pageSize; public int PageSize
{
get
{
return _pageSize;
}
set
{
if(_pageSize != value)
{
_pageSize = value;
OnPropertyChanged("PageSize");
}
}
} private int _currentPage; public int CurrentPage
{
get
{
return _currentPage;
} set
{
if(_currentPage != value)
{
_currentPage = value;
OnPropertyChanged("CurrentPage");
}
}
} private int _totalPage; public int TotalPage
{
get
{
return _totalPage;
} set
{
if(_totalPage != value)
{
_totalPage = value;
OnPropertyChanged("TotalPage");
}
}
} private ObservableCollection<FakeDatabase> _fakeSoruce; public ObservableCollection<FakeDatabase> FakeSource
{
get
{
return _fakeSoruce;
}
set
{
if(_fakeSoruce != value)
{
_fakeSoruce = value;
OnPropertyChanged("FakeSource");
}
}
} private List<FakeDatabase> _source; public MainViewModel()
{
_currentPage = 1; _pageSize = 20; FakeDatabase fake = new FakeDatabase(); _source = fake.GenerateFakeSource(); _totalPage = _source.Count / _pageSize; _fakeSoruce = new ObservableCollection<FakeDatabase>(); List<FakeDatabase> result = _source.Take(20).ToList(); _fakeSoruce.Clear(); _fakeSoruce.AddRange(result); _firstPageCommand = new DelegateCommand(FirstPageAction); _previousPageCommand = new DelegateCommand(PreviousPageAction); _nextPageCommand = new DelegateCommand(NextPageAction); _lastPageCommand = new DelegateCommand(LastPageAction);
} private void FirstPageAction()
{
CurrentPage = 1; var result = _source.Take(_pageSize).ToList(); _fakeSoruce.Clear(); _fakeSoruce.AddRange(result);
} private void PreviousPageAction()
{
if(CurrentPage == 1)
{
return;
} List<FakeDatabase> result = new List<FakeDatabase>(); if(CurrentPage == 2)
{
result = _source.Take(_pageSize).ToList();
}
else
{
result = _source.Skip((CurrentPage - 2) * _pageSize).Take(_pageSize).ToList();
} _fakeSoruce.Clear(); _fakeSoruce.AddRange(result); CurrentPage--;
} private void NextPageAction()
{
if(CurrentPage == _totalPage)
{
return;
} List<FakeDatabase> result = new List<FakeDatabase>(); result = _source.Skip(CurrentPage * _pageSize).Take(_pageSize).ToList(); _fakeSoruce.Clear(); _fakeSoruce.AddRange(result); CurrentPage++;
} private void LastPageAction()
{
CurrentPage = TotalPage; int skipCount = (_totalPage - 1) * _pageSize;
int takeCount = _source.Count - skipCount; var result = _source.Skip(skipCount).Take(takeCount).ToList(); _fakeSoruce.Clear(); _fakeSoruce.AddRange(result);
}
}
绑定到UI的数据源只是需要显示的数据,不会把所有数据都取出来。当选择显示页数时,只需要将新的数据源附上即可。
总结:如果需要对该分页控件进行扩展,例如,增加每页显示条数功能,只需要在Pager控件中增加相应的依赖属性即可。
感谢您的阅读,代码点击这里下载。
WPF 实现 DataGrid/ListView 分页控件的更多相关文章
- WPF最简单的分页控件
背景:最近在写项目的时候需要写一个简单的分页功能,因项目需要,没有改为MVVM模式,只需要在后台实现 1.呈现效果如下: 接下来就来上代码,看看怎么实现的 1.界面代码 <StackPanel ...
- WPF自定义DataGrid分页控件
新建Custom Control,名:PagingDataGrid 打开工程下面的Themes\Generic.xaml xaml里面代码替换如下 <Style x:Key="{x:T ...
- 两款不同应用场景的Wpf分页控件
简介 今天给大家分享两个Wpf分页控件,本篇博客主要介绍一些实现思路和使用方法,具体实现和应用代码请参考文末的Demo链接 废话不多说,先看一下效果~ (两款控件显示效果是一样的) 实现思路 一款控件 ...
- ASP.NET使用ListView数据绑定控件和DataPager实现数据分页显示(一)
为什么使用ListView+DataPager的方式实现分页显示? .net提供的诸多数据绑定控件,每一种都有它自己的优点和缺点.如果需要对数据进行操作,如果数据量不大的情况下,DataList和Gr ...
- WPF 分页控件 WPF 多线程 BackgroundWorker
WPF 分页控件 WPF 多线程 BackgroundWorker 大家好,好久没有发表一篇像样的博客了,最近的开发实在头疼,很多东西无从下口,需求没完没了,更要命的是公司的开发从来不走正规流程啊, ...
- WPF管理系统自定义分页控件 - WPF特工队内部资料
最近做一个演示的管理系统项目,需要用到分页控件,在网上找了很多,依然找到与UI模版匹配的,最后干脆自己写一个. 分页控件分析: 1.分页控件分简单显示和复杂显示两种: 2.包含上一页.下一页以及页码明 ...
- WPF 分页控件的实现 -用户控件
效果图:
- WPF自定义分页控件,样式自定义,简单易用
WPF自定义分页控件 做了许久伸手党,终于有机会贡献一波,搜索一下WPF分页控件,还是多,但是不太通用,主要就是样式问题,这个WPF很好解决,还有一个就是分页控件嘛,只关心几个数字的变动就行了,把页码 ...
- 基于WPF系统框架设计(10)-分页控件设计
背景 最近要求项目组成员开发一个通用的分页组件,要求是这个组件简单易用,通用性,兼容现有框架MVVM模式,可是最后给我提交的成果勉强能够用,却欠少灵活性和框架兼容性. 设计的基本思想 传入数据源,总页 ...
随机推荐
- 解决 Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in
转载 php 5个版本,5.2.5.3.5.4.5.5,怕跟不上时代,新的服务器直接上5.5,但是程序出现如下错误:Deprecated: mysql_connect(): The mysql ext ...
- js-JavaScript高级程序设计学习笔记19
第22章 高级技巧 1.高级函数 1.安全的类型检测. typeof,instanceof并非完全可靠. 安全的类型检测:使用Object原生的toString()方法. function isArr ...
- 刚开始用git遇到的无法提交变更的问题
原来我在目录里打开命令行,git bash默认执行的目录是c:/users了,错误的使用了git init,把$HOME 路径下的所有文件载入 git 仓库了,删除$HOME 路径下的".g ...
- 有用的git建议
这篇文章的目的是给经常使用git管理项目提供一个有益的提醒.如果你是git新手,可以先阅读文后的引用部分,然后在回头阅读此篇文章.在介绍git命令之前,你可以先看看来自 on-my-zsh 提供的别名 ...
- wpf 客户端 添加qq客服咨询
使用qq推广 站点:http://shang.qq.com/v3/widget.html 复制里面的html代码: <a target=" src="http://wpa.q ...
- <<< html5本地储存
类似与Cookies,但由于Cookies储存量太小,大小也只有4-5KB的样子,html5的本地储存能存5M大小的数据 html5本地储存属性有,localStorage和sessionStorag ...
- <<< struts 的一系列介绍
struts有什么用? 以前使用servlet开发应用系统的人深深感受到在java代码中嵌入大量html代码是一件非常痛苦的事,于是sun推出了JSP,解决了java代码中嵌入html代码的问题.但是 ...
- eclipse中SSH三大框架环境搭建<三>
相关链接: eclipse中SSH三大框架环境搭建<一> eclipse中SSH三大框架环境搭建<二> 引言:通过上两篇文章我们已经可以掌握struts2和spring的环境的 ...
- windows bat 设置代理上网脚本bat
取消IE代理服务器 ****************************************************************************************** ...
- AE开发实现Spatial Join Analysis
总体网上资料不多,包括esri帮助文档都写的很简单,没有各个string参数如match_option之类的可以输入的string限制,导致在摸索中gp.Execute时报错n回. 结合网上搜集资料及 ...