当前位置: 首页 > news >正文

WPF基于MVVM实现自定义分页控件

本文主要用于介绍WPF基于MVVM实现自定义分页控件的代码实现。
主要功能: 自定义页码,当前页/总页数, 上一页,下一页,返回首页,返回最后一页, 利用FontAwesome作为FontFamily实现icon的功能。

本代码中的ViewModelBase的实现请参照另一篇文章:WPF MVVM ViewModelBase(造轮子实现类似MVVMLight的功能)

1. 创建PaginationControl

1.1 Color Brush
<SolidColorBrush x:Key="HighlightBrush" Color="#E84315" /> <SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
1.2 PaginationControl.xaml.cs

不用更改任何代码

1.3 PaginationControl.xaml
<UserControl x:Class="MES.UI.Views.CustomControls.PaginationControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:local="clr-namespace:MES.UI.Views.CustomControls" mc:Ignorable="d" Height="45"> <UserControl.Resources> <Style x:Key="paginationTB" TargetType="{x:Type TextBlock}"> <Setter Property="FontSize" Value="20"/> <Setter Property="FontFamily" Value="pack://application:,,,/Resources/#FontAwesome"/> <Setter Property="Margin" Value="5,15,5,10"/> <Setter Property="Foreground" Value="{StaticResource HighlightBrush}"/> <Setter Property="Cursor" Value="Hand"/> <Style.Triggers> <Trigger Property="IsEnabled" Value="True"> <Setter Property="Foreground" Value="{StaticResource HighlightBrush}"/> </Trigger> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/> </Trigger> </Style.Triggers> </Style> </UserControl.Resources> <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> <TextBlock Text="Page Size:" Margin="5,15,5,10"></TextBlock> <ComboBox x:Name="PageSizeComboBox" ItemsSource="{Binding PageSizes}" SelectedItem="{Binding PageSize}" Width="70" VerticalAlignment="Center" HorizontalAlignment="Center"/> <TextBlock Style="{StaticResource paginationTB}" IsEnabled="{Binding EnabledPreviousButton}" Text="&#xf100;" x:Name="btnFirstPage" ToolTip="First Page"> <i:Interaction.Triggers> <i:EventTrigger EventName="MouseLeftButtonDown"> <i:InvokeCommandAction Command="{Binding FirstPageCommand}"/> </i:EventTrigger> </i:Interaction.Triggers> </TextBlock> <TextBlock Style="{StaticResource paginationTB}" IsEnabled="{Binding EnabledPreviousButton}" Text="&#xf104;" x:Name="btnPrevious" ToolTip="Previouse"> <i:Interaction.Triggers> <i:EventTrigger EventName="MouseLeftButtonDown"> <i:InvokeCommandAction Command="{Binding PreviousPageCommand}"/> </i:EventTrigger> </i:Interaction.Triggers> </TextBlock> <TextBlock Name="txtCurrentPageTextBlock" Text="{Binding CurrentPageText}" Margin="5,15,5,10" VerticalAlignment="Center" /> <TextBlock Style="{StaticResource paginationTB}" IsEnabled="{Binding EnabledNextButton}" Text="&#xf105;" x:Name="btnNext" ToolTip="Next" > <i:Interaction.Triggers> <i:EventTrigger EventName="MouseLeftButtonDown"> <i:InvokeCommandAction Command="{Binding NextPageCommand}"/> </i:EventTrigger> </i:Interaction.Triggers> </TextBlock> <TextBlock Style="{StaticResource paginationTB}" IsEnabled="{Binding EnabledNextButton}" Text="&#xf101;" x:Name="btnLastPage" ToolTip="Last Page" > <i:Interaction.Triggers> <i:EventTrigger EventName="MouseLeftButtonDown"> <i:InvokeCommandAction Command="{Binding LastPageCommand}"/> </i:EventTrigger> </i:Interaction.Triggers> </TextBlock> </StackPanel> </UserControl>

2. 创建PaginationControlViewModel

/// <summary>/// Pagination Control ViewModel/// </summary>publicclassPaginationControlViewModel:ViewModelBase{#regionPagination paramtersprivateint_currentPage;privateint_totalItems;privateint_pageSize=1;publicintTotalItems{get=>_totalItems;set{_totalItems=value;OnPropertyChanged(nameof(TotalItems));OnPropertyChanged(nameof(TotalPages));OnPropertyChanged(nameof(CurrentPageText));SetButtonStatus();}}publicintPageSize{get=>_pageSize;set{_pageSize=value;OnPropertyChanged(nameof(PageSize));OnPageChanged();}}publicintCurrentPage{get=>_currentPage;set{if(_currentPage!=value){_currentPage=value;OnPropertyChanged(nameof(CurrentPage));OnPageChanged();}}}publicstringCurrentPageText{get{return$"Page{CurrentPage}of{TotalPages}";}}publicintTotalPages=>(TotalItems+PageSize-1)/PageSize;privateObservableCollection<int>_pageSizes;publicObservableCollection<int>PageSizes{get{return_pageSizes;}set{_pageSizes=value;OnPropertyChanged(nameof(PageSizes));}}privatebool_enabledPreviousButton;publicboolEnabledPreviousButton{get{return_enabledPreviousButton;}set{_enabledPreviousButton=value;OnPropertyChanged(nameof(EnabledPreviousButton));}}privatebool_enabledNextButton;publicboolEnabledNextButton{get{return_enabledNextButton;}set{_enabledNextButton=value;OnPropertyChanged(nameof(EnabledNextButton));}}#endregionpublicICommandFirstPageCommand{get;}publicICommandPreviousPageCommand{get;}publicICommandNextPageCommand{get;}publicICommandLastPageCommand{get;}publiceventEventHandlerPageChanged;privateboolisInitialized=false;// avoid call OnPageChanged in initialpublicPaginationControlViewModel(){_pageSizes=newObservableCollection<int>{1,20,50,100,200,300,500};CurrentPage=1;// Initialize to the first pagePageSize=AgencyCRMConstants.DefaultPageSize;FirstPageCommand=newRelayCommand(_=>CurrentPage=1);PreviousPageCommand=newRelayCommand(_=>{if(CurrentPage>1)CurrentPage--;});NextPageCommand=newRelayCommand(_=>{if(CurrentPage<TotalPages)CurrentPage++;});LastPageCommand=newRelayCommand(_=>CurrentPage=TotalPages);isInitialized=true;}protectedvirtualvoidOnPageChanged(){if(isInitialized){PageChanged?.Invoke(this,EventArgs.Empty);}}privatevoidSetButtonStatus(){if(isInitialized){if(CurrentPage>1){EnabledPreviousButton=true;}else{EnabledPreviousButton=false;}if(CurrentPage>=1&&CurrentPage<TotalPages){EnabledNextButton=true;}else{EnabledNextButton=false;}}else{EnabledNextButton=false;EnabledPreviousButton=false;}}}

3. 调用

3.1 在CompanyListViewModel中引用PaginationControlViewModel
publicclassCompanyListViewModel:ViewModelBase,IViewModelDispose{#regionAgency.CRM API UrlsprivateconststringGetByCompanyNameAsync="api/Company/GetByCompanyName?CompanyName={0}&pageNumber={1}&pageSize={2}";#endregion#regionModelsprivatereadonlyIMESHttpClientService_mesHttpClientService;privateBackgroundWorker_backgroundWorker;publicPaginationControlViewModelPaginationViewModel;privatestring?_CompanyName;publicstring?CompanyName{get{return_CompanyName;}set{_CompanyName=value;OnPropertyChanged(nameof(CompanyName));}}privatebool_isEnableExport;publicboolIsEnableExport{get{return_isEnableExport;}set{_isEnableExport=value;OnPropertyChanged(nameof(IsEnableExport));}}privateCompanyDto?_selectedCompany;publicCompanyDto?SelectedCompany{get{return_selectedCompany;}set{_selectedCompany=value;OnPropertyChanged(nameof(SelectedCompany));}}privateObservableCollection<CompanyDto>_CompanyList;publicObservableCollection<CompanyDto>CompanyList{get{return_CompanyList;}set{_CompanyList=value;OnPropertyChanged(nameof(CompanyList));}}privateintpageSize=MESConstants.DefaultPageSize;privateintcurrentPage=1;#endregion#regionctorpublicCompanyListViewModel(){_mesHttpClientService=NInjectBase.Kernel.Get<IMESHttpClientService>();_CompanyList=new();_backgroundWorker=newBackgroundWorker();_backgroundWorker.DoWork+=BackgroundWorker_DoWork;_backgroundWorker.RunWorkerCompleted+=BackgroundWorker_RunWorkerCompleted;InitialParameters();}privatevoidInitialParameters(){_CompanyName=string.Empty;PaginationViewModel=newPaginationControlViewModel();PaginationViewModel.PageSize=MESConstants.DefaultPageSize;_selectedCompany=new();PaginationInitial();}#endregion#regionICommandspublicICommand?RefreshRecordsCommand{get{returnnewDelegateCommand(()=>{RefreshRecords();});}}publicICommand?ResetFilterCommand{get{returnnewDelegateCommand(()=>{ResetFilterFunction();});}}#endregion#regionFunctionsprivatevoidResetFilterFunction(){InitialParameters();RefreshRecords();}publicvoidRefreshRecords(){AppEvents.Instance.StartProgressBar(this,newProgressBarDisplayEventArgs(AppConstants.ProgressBarMessages.Generic.LOADING));_backgroundWorker.RunWorkerAsync(newList<string>(){CompanyName,currentPage.ToString(),pageSize.ToString()});}privatevoidBackgroundWorker_RunWorkerCompleted(object?sender,RunWorkerCompletedEventArgse){if(e.Error==null){varresult=e.ResultasPagedResultDto<CompanyDto>;if(result!=null){int.TryParse(result.TotalCount.ToString(),outvartotalCount);PaginationViewModel.TotalItems=totalCount;CompanyList=result.Items;this.IsEnableExport=CompanyList?.Count>0;}else{this.IsEnableExport=false;}}AppEvents.Instance.StopProgressBar(this);}privatevoidBackgroundWorker_DoWork(object?sender,DoWorkEventArgse){try{varparameters=e.ArgumentasList<string>;if(parameters==null||parameters.Count!=3)return;usingvarhttpClient=_mesHttpClientService.GetHttpClient();stringurlWithParameters=string.Format(GetByCompanyNameAsync,parameters[0],parameters[1],parameters[2]);varresponse=httpClient.GetAsync(urlWithParameters).Result;if(response.IsSuccessStatusCode){varjson=response.Content.ReadAsStringAsync().Result;varresult=JsonConvert.DeserializeObject<PagedResultDto<CompanyDto>>(json);e.Result=result;}}catch(Exceptionex){Log.Error("Error loading CRM users",ex);}}publicvoidDisposeRecordsAndEvents(){CompanyList=new();_backgroundWorker.DoWork-=BackgroundWorker_DoWork;_backgroundWorker.RunWorkerCompleted-=BackgroundWorker_RunWorkerCompleted;_backgroundWorker.Dispose();PaginationDispose();}#endregion#regionPaginationprivatevoidPaginationInitial(){PaginationViewModel=new();PaginationViewModel.PageChanged+=PaginationControlViewModel_PageChanged;}privatevoidPaginationDispose(){PaginationViewModel.PageChanged-=PaginationControlViewModel_PageChanged;}privatevoidPaginationControlViewModel_PageChanged(object?sender,EventArgse){pageSize=PaginationViewModel.PageSize;currentPage=PaginationViewModel.CurrentPage;RefreshRecords();}#endregion}
3.2 CompanyList.xaml中添加PaginationControl
<CustomControls:PaginationControl x:Name="paginationControl"></CustomControls:PaginationControl>
3.3 CompanyList.xaml.cs中为PaginationControl指定DataContext
privatevoidUserControl_Loaded(objectsender,System.Windows.RoutedEventArgse){paginationControl.DataContext=ViewModel.PaginationViewModel;ViewModel.RefreshRecords();}

4. 最终实现效果

http://www.jsqmd.com/news/145438/

相关文章:

  • openKylin 远程调试不用愁!CPolar 让 SSH 服务轻松穿透内网
  • 【计算机毕业设计案例】基于springboot的旅拍在线婚纱摄影网站的设计与实现套餐选购 - 档期预约 - 作品互动” 一体化平台(程序+文档+讲解+定制)
  • 为什么大模型会出现幻觉
  • Coolutils Total Outlook Converter(邮件格式转换工具) 多语言安装版
  • 【课程设计/毕业设计】基于Springboot+vue的在线拍卖网站设计基于springboot的拍卖网站的设计与实现【附源码、数据库、万字文档】
  • Java毕设项目:基于springboot的旅拍在线婚纱摄影网站的设计与实现(源码+文档,讲解、调试运行,定制等)
  • Java毕设项目推荐-基于springboot的旅拍在线婚纱摄影网站的设计与实现目的地推荐、在线预约、风格展示、套餐预订、行程规划【附源码+文档,调试定制服务】
  • 超强AI智能修图魔法换天AI光源傻瓜式调色!
  • Comtos Linux (朱雀) 系统安装——原理引导,启发式安装
  • ZX-560 兆芯加固笔记本
  • Claude code功能简介
  • 弹窗列表-时间筛选bug
  • 3.2.1 虚拟内存的基本概念
  • PassFab 4EasyPartition(系统迁移工具)
  • 【课程设计/毕业设计】基于springboot的马蜂窝书店网站书籍展示销售、活动管理、会员体系、书店管理【附源码、数据库、万字文档】
  • 计算机Java毕设实战-基于springboot的旅拍在线婚纱摄影网站的设计与实现摄影师团队、服装套数、住宿安排【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • Windows系统文件wshbth.dll丢失损坏 下载方法
  • Java毕设选题推荐:基于springboot的旅拍在线婚纱摄影网站的设计与实现旅拍路线、筛选摄影风格、预约拍摄服务【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 如何评估企业的区块链数字版权交易平台
  • 计算机Java毕设实战-基于springboot的拍卖网站的设计与实现拍卖商品管理、历史竞拍管理【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • 宇宙密码:数字 0.01 如何颠覆人类宇宙观
  • 2025最新!MBA论文必备10个AI论文平台深度测评
  • 医疗多尺度时空建模漏关键因素 补动态参数调整才稳住疫情预测
  • LaTeX 速查表
  • 揭秘DeepSeek:AI助手的10大核心功能
  • 软件工程学习日志2025.12.26
  • 与AI共舞:在智能辅助时代守护学术论文的“人类指纹”
  • 聚焦GEO优化,依托GEO优化,GEO优化荣登各行业推广首选榜单 - 源码云科技
  • 【毕业设计】基于springboot的启梦校园招聘平台(源码+文档+远程调试,全bao定制等)
  • Windows系统文件X3DAudio1_7.dll丢失损坏 下载方法