WPF自定义分页控件

前序

做一个设备数据点调试工具。

需求

实现一个分页的组件,总数据、总分页、目标页、上一页、下一页和分页大小。

基础样式ui Handyui
文档地址

实现结果

在这里插入图片描述

思路

  1. 使用用户控件
  2. 使用自定义控件
    在这里插入图片描述
    使用用户控件已经满足实现分页控件,暂时不研究自定义控件。

自定义控件封装主要涉及

  1. 依赖属性
  2. 查询事件

控件内注册依赖属性并使用可以绑定更新

        /// <summary>
    /// 总条数
    /// </summary>
    public long Total
    {
        get { return (long)GetValue(TotalProperty); }
        set { SetValue(TotalProperty, value); }
    }
    public static readonly DependencyProperty TotalProperty =
        DependencyProperty.Register("Total", typeof(long), typeof(Pagination), new PropertyMetadata(0l, (s, e) =>
        {
            ((Pagination)s).Total = (long)e.NewValue;
        }));

控件内注册依赖属性命令类型

 /// <summary>
    /// 上一页
    /// </summary>
    public static readonly DependencyProperty FindPreCommandProperty =
        DependencyProperty.Register("PreCommand", typeof(RelayCommand), typeof(Pagination), new PropertyMetadata(null,
            (o, args) =>
            {
                ((Pagination)o).PreCommand = (RelayCommand)args.NewValue;
            } ));
    public RelayCommand PreCommand
    {
        get { return (RelayCommand)GetValue(FindPreCommandProperty); }
        set { SetValue(FindPreCommandProperty, value); }
    }

编码

控件 Pagination.xaml
<UserControl x:Class="DeviceData.Views.Controls.Pagination"
             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:local="clr-namespace:DeviceData.Views.Controls"
             xmlns:hc="https://handyorg.github.io/handycontrol"
             mc:Ignorable="d" 
             Background="Transparent" Height="65" Width="680">
    <StackPanel Orientation="Horizontal" Margin="10" VerticalAlignment="Center">
        <TextBlock Text="共计:"  VerticalAlignment="Center" Foreground="White"  Background="Transparent" />
        <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=Total}" Margin="20,0,0,0"
                   Foreground="White"  Background="Transparent"  VerticalAlignment="Center"/>
        <TextBlock Text="条数据" Margin="20,0,0,0"  Foreground="White"  Background="Transparent" VerticalAlignment="Center"/>
        <TextBlock Text="" Margin="20,0,0,0"  Foreground="White"  Background="Transparent" VerticalAlignment="Center"/>
        <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=Page, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="10,0,0,0"  
                   Foreground="White"  Background="Transparent" VerticalAlignment="Center"/>
        <TextBlock Text="" Margin="10,0,0,0"  Foreground="White"  Background="Transparent" VerticalAlignment="Center"/>
        <TextBox Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=Current, Mode=OneWay}"
                 Margin="20,0,0,0" Width="60"  Foreground="White"  Background="Transparent" VerticalAlignment="Center"/>
        <Button Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=GoCommand}"
                Content="GO" Margin="20,0,0,0" Width="40"  Foreground="White"  Background="Transparent" VerticalAlignment="Center"/>
        <Button Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=PreCommand}"
                Content="上一页" Margin="20,0,0,0" Width="80"  Foreground="White"  Background="Transparent" VerticalAlignment="Center"/>
        <Button Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=NextCommand}"
                Content="下一页" Margin="20,0,0,0" Width="80"  Foreground="White"  Background="Transparent" VerticalAlignment="Center"/>
        <ComboBox hc:DropDownElement.ConsistentWidth="False" Width="80" Foreground="Green"  Background="Transparent"  Margin="30,0,0,0" 
                  ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=PageSizes}"
                  SelectedValue="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=PageSize, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedIndex="0"
                  
                  />

    </StackPanel>
</UserControl>
控件 Pagination.cs
using System.Windows;
using System.Windows.Controls;
using CommunityToolkit.Mvvm.Input;

namespace DeviceData.Views.Controls;

public partial class Pagination : UserControl
{
    public Pagination()
    {
        InitializeComponent();       
    }

    #region 分页数据属性
    /// <summary>
    /// 总条数
    /// </summary>
    public long Total
    {
        get { return (long)GetValue(TotalProperty); }
        set { SetValue(TotalProperty, value); }
    }
    public static readonly DependencyProperty TotalProperty =
        DependencyProperty.Register("Total", typeof(long), typeof(Pagination), new PropertyMetadata(0l, (s, e) =>
        {
            ((Pagination)s).Total = (long)e.NewValue;
        }));

    
    /// <summary>
    /// 总页数
    /// </summary>
    public int Page
    {
        get { return (int)GetValue(PageProperty); }
        set { SetValue(PageProperty, value); }
    }

    public static readonly DependencyProperty PageProperty =
        DependencyProperty.Register("Page", typeof(int), typeof(Pagination),
            new PropertyMetadata(0, (o, args) =>
            {
                ((Pagination)o).Page = (int)args.NewValue;
            }));
    
    /// <summary>
    /// 当前页
    /// </summary>
    public int Current
    {
        get { return (int)GetValue(CurrentProperty); }
        set { SetValue(CurrentProperty, value); }
    }
    public static readonly DependencyProperty CurrentProperty =
        DependencyProperty.Register("Current", typeof(int), typeof(Pagination),   new PropertyMetadata(1, (o, args) =>
        {
            ((Pagination)o).Page = (int)args.NewValue;
        }));
    
    /// <summary>
    /// 分页大小列表
    /// </summary>
    public List<int> PageSizes
    {
        get { return (List<int>)GetValue(PageSizesProperty); }
        set { SetValue(PageSizesProperty, value); }
    }
    public static readonly DependencyProperty PageSizesProperty =
        DependencyProperty.Register("PageSizes", typeof(List<int>), typeof(Pagination),  new PropertyMetadata(null, (o, args) =>
        {
            ((Pagination)o).PageSizes = (List<int>)args.NewValue;
        }));
    
    /// <summary>
    /// 分页大小
    /// </summary>
    public int PageSize
    {
        get { return (int)GetValue(PageSizeProperty); }
        set { SetValue(PageSizeProperty, value); }
    }
    public static readonly DependencyProperty PageSizeProperty =
        DependencyProperty.Register("PageSize", typeof(int), typeof(Pagination),  new PropertyMetadata(0, (o, args) =>
        {
            ((Pagination)o).PageSize = (int)args.NewValue;
        }));

    #endregion

    #region 分页事件

    /// <summary>
    /// 上一页
    /// </summary>
    public static readonly DependencyProperty FindPreCommandProperty =
        DependencyProperty.Register("PreCommand", typeof(RelayCommand), typeof(Pagination), new PropertyMetadata(null,
            (o, args) =>
            {
                ((Pagination)o).PreCommand = (RelayCommand)args.NewValue;
            } ));
    public RelayCommand PreCommand
    {
        get { return (RelayCommand)GetValue(FindPreCommandProperty); }
        set { SetValue(FindPreCommandProperty, value); }
    }
    public static readonly DependencyProperty NextCommandProperty =
        DependencyProperty.Register("NextCommand", typeof(RelayCommand), typeof(Pagination), new PropertyMetadata(null,
            (o, args) =>
            {
                ((Pagination)o).NextCommand = (RelayCommand)args.NewValue;
            } ));
    public RelayCommand NextCommand
    {
        get { return (RelayCommand)GetValue(NextCommandProperty); }
        set { SetValue(NextCommandProperty, value); }
    }
    public static readonly DependencyProperty GoCommandProperty =
        DependencyProperty.Register("GoCommand", typeof(RelayCommand), typeof(Pagination), new PropertyMetadata(null,
            (o, args) =>
            {
                ((Pagination)o).GoCommand = (RelayCommand)args.NewValue;
            } ));
    public RelayCommand GoCommand
    {
        get { return (RelayCommand)GetValue(GoCommandProperty); }
        set { SetValue(GoCommandProperty, value); }
    }
    
    #endregion    

}
使用控件窗体或控件
  1. 导入命名控件
    xmlns:ctls="clr-namespace:DeviceData.Views.Controls"
  1. 使用控件,通过ViewModel进行数据绑定
<ctls:Pagination Margin="5" Total="{Binding PagenationModel.Total}" Current="{Binding PagenationModel.Current}" 
                          Page="{Binding PagenationModel.page}" PageSize="{Binding PagenationModel.Pages}"
                          PageSizes="{Binding PagenationModel.PageSizes}" PreCommand="{Binding PagenationModel.FindPreCommand}"
                          NextCommand="{Binding PagenationModel.FindNextCommand}"  GoCommand="{Binding PagenationModel.FindTargetCommand}"
                          >
         </ctls:Pagination>

封装的分页数据模型 (参考)

using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace DeviceData.Models;

public class PagenationModel<T> : ObservableObject
{
    private long total = 0;
    public long Total
    {
        get => total;
        set => SetProperty(ref total, value);
    }
    
    private int page = 1;
    public int Page
    {
        get => page;
        set => SetProperty(ref page, value);
    }
    
    private int current = 1;
    public int Current
    {
        get => current;
        set => SetProperty(ref current, value);
    }
    
    private List<int> pageSizes = new List<int>(){10, 20, 30, 40, 50};
    public List<int> PageSizes
    {
        get => pageSizes;
        set => SetProperty(ref pageSizes, value);
    }

    /// <summary>
    /// 上一页
    /// </summary>
    private RelayCommand findPreCommand;
    public RelayCommand FindPreCommand
    {
        get => findPreCommand;
        set => SetProperty(ref findPreCommand, value);
    }
    /// <summary>
    /// 下一页
    /// </summary>
    private RelayCommand findNextCommand;
    public RelayCommand FindNextCommand
    {
        get => findNextCommand;
        set => SetProperty(ref findNextCommand, value);
    }
    /// <summary>
    /// 目标页
    /// </summary>
    private RelayCommand findTargetCommand;
    public RelayCommand FindTargetCommand
    {
        get => findTargetCommand;
        set => SetProperty(ref findTargetCommand, value);
    }    
    
    private ObservableCollection<T>  rows = new ObservableCollection<T>();
    public ObservableCollection<T> Rows
    {
        get => rows;
        set => SetProperty(ref rows, value);
    }   

}

MVVM框架用的是微软的 CommunityToolkit.Mvvm
官方文档

效果图

软件暂未开发完成,等开发完成再把源码地址放出来。
在这里插入图片描述

  • 16
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF自定义DataGrid控件是通过继承现有的DataGrid类,并在其基础上进行修改和扩展来实现的。 自定义DataGrid控件的步骤如下: 1. 创建一个自定义的类,继承自DataGrid。例如,可以命名为CustomDataGrid。 2. 在CustomDataGrid类中,可以添加额外的属性、依赖属性或附加属性,用于自定义DataGrid控件的特定行为或外观。 3. 重写或扩展DataGrid的现有方法、事件和样式,以满足自定义需求。例如,可以重写OnApplyTemplate()方法以应用自定义样式。 4. 根据需要,可以添加新的功能或控件,例如自定义列、单元格、行、排序、筛选、分页等等。 5. 在CustomDataGrid类中,可以通过编写自定义的模板(Template)来修改DataGrid的外观。例如,可以通过修改DataGrid的ControlTemplate来改变整个DataGrid的显示风格。 6. 编写完自定义类后,可以在XAML中使用自定义DataGrid控件,通过添加命名空间引用并将CustomDataGrid作为一个控件使用。可以设置自定义属性、事件和样式,达到期望的效果。 通过自定义DataGrid控件,可以根据实际需求对其进行扩展和修改,以满足特定的业务需求。由于WPF提供了强大的样式、模板和继承机制,因此可以轻松地自定义DataGrid控件,并且可以实现高度的灵活性和可扩展性。这样,可以根据项目的需求和用户的喜好来创建独特的、具有个性化的DataGrid控件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值