|
自定义分页控件
tip: 该控件的样式用的是materialDesign库,需要下载Nuget包
Code
- <UserControl
- x:
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- x:Name="pagingControl"
- TextElement.FontSize="14"
- mc:Ignorable="d">
- <UserControl.Resources>
-
- </UserControl.Resources>
- <StackPanel DataContext="{Binding ElementName=pagingControl}" Orientation="Horizontal">
- <Button
- Click="Button_FirstPage_Click"
- ToolTip="首页">
- <materialDesign:PackIcon
- Width="24"
- Height="24"
- VerticalAlignment="Center"
- Kind="PageFirst" />
- </Button>
- <Button
- Margin="10,0,10,0"
- Click="Button_Previous_Click"
- ToolTip="上一页">
- <materialDesign:PackIcon
- Width="20"
- Height="20"
- VerticalAlignment="Center"
- Kind="ArrowLeftCircle" />
- </Button>
- <TextBlock VerticalAlignment="Center" Text="{Binding CurrentPageIndex}" />
- <TextBlock VerticalAlignment="Center">/</TextBlock>
- <TextBlock VerticalAlignment="Center" Text="{Binding TotalPageCount}" />
- <Button
- Width="26"
- Height="26"
- Margin="10,0,0,0"
- Click="Button_Next_Click"
- ToolTip="下一页">
- <materialDesign:PackIcon
- Width="20"
- Height="20"
- VerticalAlignment="Center"
- Kind="ArrowRightCircle" />
- </Button>
- <Button
- Margin="10,0,0,0"
- Click="Button_Last_Click"
- ToolTip="尾页">
- <materialDesign:PackIcon
- Width="24"
- Height="24"
- VerticalAlignment="Center"
- Kind="PageLast" />
- </Button>
- <TextBlock Margin="20,0,0,0" VerticalAlignment="Center">共</TextBlock>
- <TextBlock
- Margin="5,0,0,0"
- VerticalAlignment="Center"
- Text="{Binding TotalCount}" />
- <TextBlock Margin="5,0,0,0" VerticalAlignment="Center">条记录</TextBlock>
- <Separator
- Height="14"
- Margin="10,0,0,0"
- BorderThickness="0.5"
- />
- <TextBlock Margin="10,0,0,0" VerticalAlignment="Center">每页数量</TextBlock>
- <ComboBox
- MinWidth="50"
- Margin="5,0,0,0"
- VerticalContentAlignment="Center"
- ItemsSource="{Binding PagesSizes}"
- SelectedIndex="0"
- SelectedItem="{Binding CurrentPageSize}"
- SelectionChanged="ComboBox_PageSize_SelectionChanged" />
- <Separator
- Height="14"
- Margin="10,0,0,0"
- BorderThickness="0.5"
- />
- <TextBlock Margin="10,0,0,0" VerticalAlignment="Center">跳转到第</TextBlock>
- <TextBox
- Width="50"
- Margin="5,0,5,0"
- VerticalAlignment="Center"
- HorizontalContentAlignment="Center"
- Text="{Binding GotoPageIndex}" />
- <TextBlock VerticalAlignment="Center">页</TextBlock>
- <Button
- Margin="5,0,0,0"
- Click="Button_Goto_Click"
- ToolTip="跳转">
- <materialDesign:PackIcon
- Width="24"
- Height="24"
- VerticalAlignment="Center"
- Kind="ArrowRightBold" />
- </Button>
- </StackPanel>
- </UserControl>
复制代码- public partial class PagingControl : UserControl, INotifyPropertyChanged
- {
- // 用于防抖、节流
- private readonly ConcurrentQueue<DateTime> _operationTime = new();
- //用于防抖、节流,拦截两次时间少于1秒的操作
- private readonly TimeSpan _ignoreOperationLessThen = TimeSpan.FromSeconds(1);
- public event EventHandler CanExecuteChanged;
- public event PropertyChangedEventHandler? PropertyChanged;
- #region 普通属性
- /// <summary>
- /// 能否执行状态
- /// </summary>
- public bool CanExecute => QueryCommand?.CanExecute(null) ?? true;
- //在load后是否立即触发命令和路由事件
- public bool LoadedTrigger { get; set; } = false;
- public ObservableCollection<int> PagesSizes { get; set; } = [15, 30, 60, 200, 500, 2000];
- /// <summary>
- /// 总页数
- /// </summary>
- private int _totalPageCount;
- public int TotalPageCount
- {
- get => _totalPageCount;
- set
- {
- if (_totalPageCount != value)
- {
- _totalPageCount = value;
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TotalPageCount)));
- }
- }
- }
- /// <summary>
- /// 跳转页码
- /// </summary>
- private int _gotoPageIndex;
- public int GotoPageIndex
- {
- get => _gotoPageIndex;
- set
- {
- if (_gotoPageIndex != value)
- {
- _gotoPageIndex = value;
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(GotoPageIndex)));
- }
- }
- }
- /// <summary>
- /// 当前页大小
- /// </summary>
- private int _currentPageSize = 15;
- public int CurrentPageSize
- {
- get => _currentPageSize;
- set
- {
- if (_currentPageSize != value)
- {
- _currentPageSize = value;
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentPageSize)));
- }
- }
- }
- /// <summary>
- /// 当前页码
- /// </summary>
- private int _currentPageIndex;
- public int CurrentPageIndex
- {
- get => _currentPageIndex;
- set
- {
- if (_currentPageIndex != value)
- {
- _currentPageIndex = value;
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentPageIndex)));
- }
- }
- }
- //用于外部绑定命令
- public ICommand PageQueryCommand { get; }
- #endregion
- #region 依赖属性
- /// <summary>
- /// 总数
- /// </summary>
- public int TotalCount
- {
- get { return (int)GetValue(TotalCountProperty); }
- set { SetValue(TotalCountProperty, value); }
- }
- public ICommand QueryCommand
- {
- get { return (ICommand)GetValue(QueryCommandProperty); }
- set { SetValue(QueryCommandProperty, value); }
- }
- public static readonly DependencyProperty TotalCountProperty =
- DependencyProperty.Register("TotalCount", typeof(int), typeof(PagingControl), new FrameworkPropertyMetadata(15, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, TotalCountChangedCallback));
- public static readonly DependencyProperty QueryCommandProperty =
- DependencyProperty.Register("QueryCommand", typeof(ICommand), typeof(PagingControl), new PropertyMetadata(null, QueryCommandChangedCallback));
- #endregion
- public static readonly RoutedEvent PagingChangedEvent = EventManager.RegisterRoutedEvent("PagingChanged", RoutingStrategy.Bubble, typeof(EventHandler<PagingChangedEventArgs>), typeof(PagingControl));
- public event RoutedEventHandler PagingChanged
- {
- add => AddHandler(PagingChangedEvent, value);
- remove => RemoveHandler(PagingChangedEvent, value);
- }
- /// <summary>
- /// 构造函数
- /// </summary>
- public PagingControl()
- {
- InitializeComponent();
- TotalCount = 0;
- GotoPageIndex = 1;
- CurrentPageIndex = 0;
- TotalPageCount = 0;
- PageQueryCommand = new PageQueryCommand(this);
- }
- static void TotalCountChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- PagingControl pagingControl = (PagingControl)d;
- pagingControl.ReLoad((int)e.NewValue);
- }
- static void QueryCommandChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var command = e.NewValue as ICommand;
- if (command != null)
- {
- PagingControl pagingControl = (PagingControl)d;
- command.CanExecuteChanged -= pagingControl.Command_CanExecuteChanged;
- command.CanExecuteChanged += pagingControl.Command_CanExecuteChanged;
- if (pagingControl.LoadedTrigger)
- pagingControl.FirstPage();
- }
- }
- private void Command_CanExecuteChanged(object? sender, EventArgs e)
- {
- CanExecuteChanged?.Invoke(this, e);
- IsEnabled = QueryCommand.CanExecute(null);
- }
- #region 事件
- /// <summary>
- /// 每页大小 ComboBox 变化
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void ComboBox_PageSize_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- ReLoad(TotalCount);
- CurrentPageIndex = 1;
- OnPagingChanged(CurrentPageIndex);
- e.Handled = true;
- }
- /// <summary>
- /// 首页按钮点击事件
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void Button_FirstPage_Click(object sender, RoutedEventArgs e)
- {
- FirstPage();
- e.Handled = true;
- }
- /// <summary>
- /// 尾页按钮点击事件
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void Button_Last_Click(object sender, RoutedEventArgs e)
- {
- LastPage();
- e.Handled = true;
- }
- /// <summary>
- /// 上一页按钮点击事件
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void Button_Previous_Click(object sender, RoutedEventArgs e)
- {
- PreviousPage();
- e.Handled = true;
- }
- /// <summary>
- /// 下一页按钮点击事件
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void Button_Next_Click(object sender, RoutedEventArgs e)
- {
- NextPage();
- e.Handled = true;
- }
- /// <summary>
- /// 跳转按钮点击事件
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void Button_Goto_Click(object sender, RoutedEventArgs e)
- {
- GoToPage();
- e.Handled = true;
- }
- #endregion
- private void ReLoad(int totalCount)
- {
- TotalPageCount = (totalCount + CurrentPageSize - 1) / CurrentPageSize;
- if (TotalPageCount == 0)
- CurrentPageIndex = 0;
- else if (TotalPageCount != 0 && CurrentPageIndex == 0)
- CurrentPageIndex = 1;
- }
- private bool CheckCanExcetue()
- {
- if (_operationTime.TryDequeue(out var time))
- {
- if (DateTime.Now - time < _ignoreOperationLessThen)
- return false;
- }
- _operationTime.Enqueue(DateTime.Now);
- return CanExecute;
- }
- public void FirstPage()
- {
- if (!CheckCanExcetue()) return;
- CurrentPageIndex = 1;
- OnPagingChanged(CurrentPageIndex);
- }
- public void LastPage()
- {
- if (!CheckCanExcetue()) return;
- if (TotalPageCount == 0)
- {
- OnPagingChanged(1);
- }
- else
- {
- CurrentPageIndex = TotalPageCount;
- OnPagingChanged(CurrentPageIndex);
- }
- }
- public void NextPage()
- {
- if (!CheckCanExcetue()) return;
- if (CurrentPageIndex >= TotalPageCount)
- {
- OnPagingChanged(CurrentPageIndex);
- }
- else
- {
- CurrentPageIndex++;
- OnPagingChanged(CurrentPageIndex);
- }
- }
- public void PreviousPage()
- {
- if (!CheckCanExcetue()) return;
- if (CurrentPageIndex > TotalPageCount)
- {
- CurrentPageIndex = TotalPageCount;
- }
- if (CurrentPageIndex > 1)
- {
- CurrentPageIndex--;
- OnPagingChanged(CurrentPageIndex);
- }
- else
- {
- OnPagingChanged(1);
- }
- }
- public void GoToPage()
- {
- if (!CheckCanExcetue()) return;
- if (GotoPageIndex < 1 || GotoPageIndex > TotalPageCount)
- return;
- CurrentPageIndex = GotoPageIndex;
- OnPagingChanged(CurrentPageIndex);
- }
- private void OnPagingChanged(int pageIndex)
- {
- PagingChangedEventArgs pagingChangedEventArgs = new(PagingChangedEvent, this,
- new PagingInfo(pageIndex, CurrentPageSize));
- RaiseEvent(pagingChangedEventArgs);
- QueryCommand?.Execute(new PagingInfo(pageIndex, CurrentPageSize));
- }
- }
复制代码 相关自定义类
- public record class PagingInfo(int TargetPageIndex, int PageSize);
复制代码 路由事件参数
- public class PagingChangedEventArgs(RoutedEvent routedEvent, object source, PagingInfo pageInfo) : RoutedEventArgs(routedEvent, source)
- {
- public PagingInfo PageInfo { get; set; } = pageInfo;
- }
复制代码 外部绑定命令(用于MVVM模式下,需要其它地方触发分页控件命令)
- public class PageQueryCommand : ICommand
- {
- private readonly PagingControl _pagingControl;
- public event EventHandler? CanExecuteChanged;
- public PageQueryCommand(PagingControl pagingControl)
- {
- _pagingControl = pagingControl;
- _pagingControl.CanExecuteChanged += (o, e) => CanExecuteChanged?.Invoke(o, e);
- }
- public bool CanExecute(object? parameter)
- {
- return _pagingControl?.CanExecute ?? true;
- }
- public void Execute(object? parameter)
- {
- _pagingControl.FirstPage();
- }
- }
复制代码 Demo
- 当点击分页控件按钮时会触发QueryCommand命令和路由事件,并传入相关参数,需要在查询完结果后将查询到的总数赋值给TotalCount以便更新UI显示的相关信息
- 当需要外部按钮来激发查询命令时,可绑定分页控件的pageQueryCommand
- <Button
- x:Name="buttonQuery"
- Margin="10,0,0,0"
- HorizontalAlignment="Stretch"
- Content="查询"
- Command="{Binding ElementName=pageControl, Path=PageQueryCommand}"/>
- <customControls:PagingControl
- x:Name="pageControl"
- HorizontalAlignment="Right"
- DockPanel.Dock="Bottom"
- LoadedTrigger="False"
- QueryCommand="{Binding PageQueryCommand}"
- TotalCount="{Binding TotalCount}" />
- [RelayCommand]
- private async Task PageQuery(PagingInfo pagingInfo){
- //通过数据库进行查询
- TotalCount=查出结果数量
- }
复制代码希望能给你带来帮助 --来自.net菜鸡粉丝的祝愿
来源:https://www.cnblogs.com/yinyuessh/p/18205496
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
|