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

WPF+MVVM案例实战(六)- 自定义分页控件实现

在这里插入图片描述

文章目录

  • 1、项目准备
  • 2、功能实现
    • 1、分页控件 DataPager 实现
    • 2、分页控件数据模型与查询行为
    • 3、数据界面实现
  • 3、运行效果
  • 4、源代码获取


1、项目准备

打开项目 Wpf_Examples,新建 PageBarWindow.xaml 界面、PageBarViewModel.cs ,在用户控件库 UserControlLib中创建用户控件 DataPager.xaml 文件 。如下所示:
在这里插入图片描述
注意:如果没有 Wpf_Examples 项目,可以参考 WPF+MVVM案例实战(三)- 动态数字卡片效果实现,里面详细说明了整个项目的创建过程和环境包安装。

2、功能实现

1、分页控件 DataPager 实现

DataPager.xaml 页面代码实现如下:

<UserControl x:Class="UserControlLib.DataPager"
             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:UserControlLib"
             x:Name="userControl"
         mc:Ignorable="d"
         Height="30"  HorizontalContentAlignment="Right" VerticalContentAlignment="Center">
    <Grid>
        <Grid.Resources>
            <Style x:Key="NormalTextBlockStyle" TargetType="{x:Type TextBlock}">
                <Setter Property="TextWrapping" Value="NoWrap" />
                <Setter Property="VerticalAlignment" Value="Center" />
                <Setter Property="FontSize" Value="14"></Setter>
                <Setter Property="Foreground" Value="#96bfd6" />
            </Style>
            <ControlTemplate x:Key="PageButtonTemplate" TargetType="{x:Type Button}">
                <TextBlock x:Name="textBlock" VerticalAlignment="Center" Text="{TemplateBinding Content}" HorizontalAlignment="Stretch" Cursor="Hand" Foreground="#96bfd6" />
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Foreground" TargetName="textBlock" Value="#FF554F4F" />
                        <Setter Property="Cursor" Value="None" />
                        <Setter Property="FontSize" Value="14"></Setter>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>

            <Style x:Key="LabelStyle" TargetType="{x:Type Label}">
                <Setter Property="VerticalAlignment" Value="Center" />
                <Setter Property="FontSize" Value="14"></Setter>
                <Setter Property="Foreground" Value="#FFABA5A5" />
            </Style>
            <Style x:Key="TextBoxStyle" TargetType="{x:Type TextBox}">
                <Setter Property="HorizontalAlignment" Value="Center" />
                <Setter Property="HorizontalContentAlignment" Value="Center" />
                <Setter Property="VerticalAlignment" Value="Center" />
                <Setter Property="VerticalContentAlignment" Value="Center" />
                <Setter Property="Background" Value="#FFEAEBEC" />
                <Setter Property="FontSize" Value="14"></Setter>
                <Setter Property="Foreground" Value="#96bfd6" />
                <Setter Property="BorderBrush" Value="Transparent" />
                <Setter Property="BorderThickness" Value="0" />
                <Setter Property="CharacterCasing" Value="Upper" />
                <Setter Property="InputMethod.IsInputMethodEnabled" Value="False" />
            </Style>
        </Grid.Resources>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center" x:Name="Stack_Main">
            <TextBlock Style="{DynamicResource NormalTextBlockStyle}" Text="共" />
            <TextBlock Text="{Binding TotalCount, ElementName=userControl}" Style="{DynamicResource NormalTextBlockStyle}" Margin="4,0" />
            <TextBlock Style="{DynamicResource NormalTextBlockStyle}" Text="行,每页" />
            <!--<TextBlock Text="{Binding PageSize, ElementName=userControl}" Style="{DynamicResource NormalTextBlockStyle}" Margin="4,0" />-->
            <ComboBox Grid.Column="0" Height="24" VerticalAlignment="Center" x:Name="cboxPageSize"  Padding="0" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"
                  Width="60" Margin="5,0,0,0" SelectedItem="{Binding PageSize, ElementName=userControl,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Cursor="Hand" />
            <TextBlock Text="行,第" Style="{DynamicResource NormalTextBlockStyle}" />
            <TextBlock Text="{Binding PageIndex, ElementName=userControl}" Style="{DynamicResource NormalTextBlockStyle}" Margin="4,0,2,0" />
            <TextBlock Text="/" Style="{DynamicResource NormalTextBlockStyle}" />
            <TextBlock Text="{Binding PageCount, ElementName=userControl, Mode=OneWay}" Style="{DynamicResource NormalTextBlockStyle}" Margin="2,0,4,0" />
            <TextBlock Text="页" Style="{DynamicResource NormalTextBlockStyle}" />
            <Button x:Name="btnFirst" Content="首页" FontSize="14" Template="{DynamicResource PageButtonTemplate}" VerticalAlignment="Center" Margin="10,0,0,0" Click="btnFirst_Click" IsEnabled="{Binding CanGoFirstOrPrev, ElementName=userControl}" />
            <Button x:Name="btnPrev" Content="上一页" FontSize="14" Template="{DynamicResource PageButtonTemplate}" VerticalAlignment="Center" Margin="10,0,0,0" Click="btnPrev_Click" IsEnabled="{Binding CanGoFirstOrPrev, ElementName=userControl}" />
            <Button x:Name="btnNext" Content="下一页" FontSize="14" VerticalAlignment="Center" Template="{DynamicResource PageButtonTemplate}" Margin="10,0,10,0" Click="btnNext_Click" IsEnabled="{Binding CanGoLastOrNext, ElementName=userControl}" />
        </StackPanel>
    </Grid>
</UserControl>

DataPager.cs 后台代码实现如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace UserControlLib
{
    /// <summary>
    /// DataPager.xaml 的交互逻辑
    /// </summary>
    public partial class DataPager : UserControl, INotifyPropertyChanged
    {
        /// <summary>
        /// 分页前处理的事件,如果设置e.IsCancel=True将取消分页
        /// </summary>
        //public event PageChangingRouteEventHandler PageChanging;
        / <summary>
        / 分页后处理的事件
        / </summary>
        //public event PageChangedRouteEventHandler Closed;

        public static readonly RoutedEvent PageChangedEvent = EventManager.RegisterRoutedEvent("PageChangedEvent", RoutingStrategy.Bubble,
            typeof(EventHandler<PageChangedEventArgs>), typeof(DataPager));

        public delegate void PageChangedRouteEventHandler(object sender, PageChangedEventArgs e);

        public event RoutedEventHandler PageChanged
        {
            add { this.AddHandler(PageChangedEvent, value); }
            remove { this.RemoveHandler(PageChangedEvent, value); }
        }

        //public event Action Closed;

        public DataPager()
        {
            InitializeComponent();
            BindComBox();
        }

        #region 依赖属性--------------------------------------

        /// <summary>
        /// 当前页
        /// </summary>
        public int PageIndex
        {
            get { return (int)GetValue(PageIndexProperty); }
            set { SetValue(PageIndexProperty, value); }
        }

        // Using a DependencyProperty as the backing store for CurrentPage.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PageIndexProperty =
            DependencyProperty.Register("PageIndex", typeof(int), typeof(DataPager), new UIPropertyMetadata(1, (sender, e) =>
            {
                var dp = sender as DataPager;
                dp.ChangeNavigationButtonState();
            }));

        /// <summary>
        /// 每页显示数据大小
        /// </summary>
        public int PageSize
        {
            get { return (int)GetValue(PageSizeProperty); }
            set { SetValue(PageSizeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for PageSize.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PageSizeProperty =
            DependencyProperty.Register("PageSize", typeof(int), typeof(DataPager), new UIPropertyMetadata(20, (sender, e) =>
            {
                var dp = sender as DataPager;
                if (dp == null) return;
                dp.InitData();
                dp.OnPageChanging(1);
                dp.ChangeNavigationButtonState();
            }));

        /// <summary>
        /// 记录数量
        /// </summary>
        public int TotalCount
        {
            get { return (int)GetValue(TotalCountProperty); }
            set
            {
                SetValue(TotalCountProperty, value);
            }
        }

        // Using a DependencyProperty as the backing store for TotalCount.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TotalCountProperty =
            DependencyProperty.Register("TotalCount", typeof(int), typeof(DataPager), new UIPropertyMetadata(0, (sender, e) =>
            {
                var dp = sender as DataPager;
                if (dp == null) return;
                dp.InitData();
                dp.ChangeNavigationButtonState();
            }));

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

        // Using a DependencyProperty as the backing store for PageCount.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PageCountProperty =
            DependencyProperty.Register("PageCount", typeof(int), typeof(DataPager), new UIPropertyMetadata(1));

        /// <summary>
        /// 是否可以点击首页和上一页按钮
        /// </summary>
        public bool CanGoFirstOrPrev
        {
            get
            {
                if (PageIndex <= 1) return false;
                return true;
            }
        }
        /// <summary>
        /// 是否可以点击最后页和下一页按钮
        /// </summary>
        public bool CanGoLastOrNext
        {
            get
            {
                if (PageIndex >= PageCount) return false;
                return true;
            }
        }

        #endregion 依赖属性--------------------------------------

        #region 下拉列表数据绑定-------------------------

        public void BindComBox()
        {
            List<string> pageSizeList = new List<string> { "20", "50", "100" };
            cboxPageSize.ItemsSource = pageSizeList;
            cboxPageSize.SelectedIndex = 0;
        }

        #endregion 下拉列表数据绑定-------------------------

        /// <summary>
        /// 初始化数据
        /// </summary>
        void InitData()
        {
            if (this.TotalCount == 0)
            {
                this.PageCount = 1;
            }
            else
            {
                this.PageCount = this.TotalCount % this.PageSize > 0 ? (this.TotalCount / this.PageSize) + 1 : this.TotalCount / this.PageSize;
            }
            if (this.PageIndex < 1)
            {
                this.PageIndex = 1;
            }
            if (this.PageIndex > this.PageCount)
            {
                this.PageIndex = this.PageCount;
            }
            if (this.PageSize < 1)
            {
                this.PageSize = 20;
            }
        }
        /// <summary>
        /// 点击首页按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnFirst_Click(object sender, RoutedEventArgs e)
        {
            OnPageChanging(1);
        }
        /// <summary>
        /// 点击上一页按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPrev_Click(object sender, RoutedEventArgs e)
        {
            OnPageChanging(this.PageIndex - 1);
        }
        /// <summary>
        /// 点击下一页按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnNext_Click(object sender, RoutedEventArgs e)
        {
            OnPageChanging(this.PageIndex + 1);
        }
        /// <summary>
        /// 点击末页按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnLast_Click(object sender, RoutedEventArgs e)
        {
            OnPageChanging(this.PageCount);
        }
        /// <summary>
        /// 点击跳转按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnGoTo_Click(object sender, RoutedEventArgs e)
        {
            int pageIndex = 1;
            try
            {
                //pageIndex = Convert.ToInt32(txtPageIndex.Text);
            }
            catch
            {
            }
            finally
            {
                OnPageChanging(pageIndex);
            }
        }
        /// <summary>
        /// 页码更改
        /// </summary>
        /// <param name="pageIndex"></param>
        internal void OnPageChanging(int pageIndex)
        {
            if (pageIndex < 1) pageIndex = 1;
            if (pageIndex > this.PageCount) pageIndex = this.PageCount;

            var newPageIndex = pageIndex;
            //var eventArgs = new PageChangingEventArgs() { OldPageIndex = oldPageIndex, NewPageIndex = newPageIndex };
            var eventArgs = new PageChangedEventArgs(PageChangedEvent, this);
            this.PageIndex = newPageIndex;
            RaiseEvent(eventArgs);
            //if (this.Closed != null)
            //{
            //    this.Closed();
            //}
            //if (!eventArgs.IsCancel)
            //{
            //    if (this.Closed != null)
            //    {
            //        this.Closed.Invoke();
            //    }
            //}
        }

        /// <summary>
        /// 通知导航按钮(首页,上一页,下一页,末页)状态的更改
        /// </summary>
        void ChangeNavigationButtonState()
        {
            this.NotifyPropertyChanged("CanGoFirstOrPrev");
            this.NotifyPropertyChanged("CanGoLastOrNext");
        }

        #region INotifyPropertyChanged成员

        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion INotifyPropertyChanged成员

        private void cboxPageSize_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            this.PageSize = ((System.Collections.Generic.KeyValuePair<int, string>)(cboxPageSize.SelectedItem)).Key;

            var param = new PageChangedEventArgs(PageChangedEvent, this);

            RaiseEvent(param);

            //if (Closed != null)
            //{
            //    this.Closed.Invoke();
            //}
        }

        private void TxtPageIndex_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            Regex re = new Regex("[^0-9]+");
            e.Handled = re.IsMatch(e.Text);
        }
    }

    public class PageChangedEventArgs : RoutedEventArgs
    {
        public PageChangedEventArgs(RoutedEvent routedEvent, object source) : base(routedEvent, source) { }
        public DataPager dataPager { get; set; }
    }
}


2、分页控件数据模型与查询行为

在这里插入图片描述PageBarAction.cs 代码实现如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UserControlLib.Models;

namespace UserControlLib.Actions
{
    public class PageBarAction
    {
        public static bool GetDataByPage<T>(int pageSize, int pageIndex, List<T> list, T obj) where T : DataModel
        {
            var temp = list.FirstOrDefault(t => t.Key == obj.Key);
            if (temp == null) return false;
            int index = list.IndexOf(temp);
            if (index >= pageSize * (pageIndex - 1) && index < pageSize * pageIndex)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}

DataModel.cs 数据模型如下:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows;
using CommunityToolkit.Mvvm.ComponentModel;

namespace UserControlLib.Models
{
    [Serializable]
    public class DataModel : ObservableObject
    {
        private string key = Guid.NewGuid().ToString();
        /// <summary>
        /// Key
        /// </summary>
        public string Key
        {
            get => key;
            set => SetProperty(ref key, value);
        }

        private int order = 0;
        /// <summary>
        /// 序号
        /// </summary>
        public int Order
        {
            get => order;
            set => SetProperty(ref order, value);
        }

        private bool isSelected = false;
        /// <summary>
        /// 是否选中
        /// </summary>
        public bool IsSelected
        {
            get => isSelected;
            set => SetProperty(ref isSelected, value);
        }

        private bool changedEnabled = false;
        /// <summary>
        /// 修改使能
        /// </summary>
        public bool ChangedEnabled
        {
            get => changedEnabled;
            set => SetProperty(ref changedEnabled, value);
        }

        private List<string> errors = new List<string>();
        /// <summary>
        /// 错误提示集合
        /// </summary>
        public List<string> Errors
        {
            get { return errors; }
            set { errors = value; }
        }


        private string error = string.Empty;
        /// <summary>
        /// 错误提示,未使用
        /// </summary>
        public string Error
        {
            get { return error; }
            set { error = value; }
        }

        public string this[string columnName]
        {
            get
            {
                var vc = new ValidationContext(this, null, null);
                vc.MemberName = columnName;
                var res = new List<System.ComponentModel.DataAnnotations.ValidationResult>();
                var result = this.GetType().GetProperty(columnName).GetValue(this, null);
                if (res.Count > 0)
                {
                    return string.Join(Environment.NewLine, res.Select(r => r.ErrorMessage).ToArray());
                }
                return string.Empty;
            }
        }

        public string GetHashKey()
        {
            return Guid.NewGuid().GetHashCode().ToString();
        }
    }

}

自定义控件样式如下
在这里插入图片描述

3、数据界面实现

这里我们使用 DataGrid 显示数据,用 DataPager 分页控件实现分页控制。

PageBarWindow.xaml 界面代码如下:

<Window x:Class="Wpf_Examples.Views.PageBarWindow"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Wpf_Examples.Views"
        xmlns:uc="clr-namespace:UserControlLib;assembly=UserControlLib"
        DataContext="{Binding Source={StaticResource Locator},Path=PageBar}"
        mc:Ignorable="d"
        Title="PageBarWindow" Height="450" Width="800">
    <Window.Resources>
        <!--DataGrid样式-->
        <Style TargetType="DataGrid" >
            <!--网格线颜色-->
            <Setter Property="IsReadOnly" Value="True" />
            <Setter Property="FontSize" Value="16" />
            <Setter Property="CanUserResizeColumns" Value="False"/>
            <Setter Property="CanUserResizeRows" Value="False"/>
            <Setter Property="AutoGenerateColumns" Value="False" />
            <Setter Property="CanUserAddRows" Value="False" />
            <Setter Property="BorderBrush" Value="#FFF5F7F5" />
        </Style>

        <!--标题栏样式-->
        <Style TargetType="DataGridColumnHeader" >
            <Setter Property="SnapsToDevicePixels" Value="True" />
            <Setter Property="MinWidth" Value="0" />
            <Setter Property="MinHeight" Value="28" />
            <Setter Property="FontSize" Value="16" />
            <Setter Property="Cursor" Value="Hand" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="DataGridColumnHeader">
                        <Border x:Name="BackgroundBorder" BorderThickness="0,1,0,1" Width="Auto">
                            <Grid >
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>
                                <ContentPresenter  Margin="0,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                                <Path x:Name="SortArrow" Visibility="Collapsed" Data="M0,0 L1,0 0.5,1 z" Stretch="Fill"  Grid.Column="2" Width="8" Height="6" Fill="White" Margin="0,0,50,0" 
                     VerticalAlignment="Center" RenderTransformOrigin="1,1" />
                                <Rectangle Width="1" Fill="#d6c79b" HorizontalAlignment="Right" Grid.ColumnSpan="1" />
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="Height" Value="25"/>
        </Style>
        <!--行样式触发-->
        <!--背景色改变必须先设置cellStyle 因为cellStyle会覆盖rowStyle样式-->
        <Style  TargetType="DataGridRow">
            <Setter Property="Background" Value="#F2F2F2" />
            <Setter Property="Height" Value="25"/>
            <Setter Property="Foreground" Value="Black" />
            <Style.Triggers>
                <!--隔行换色-->
                <Trigger Property="AlternationIndex" Value="0" >
                    <Setter Property="Background" Value="#e7e7e7" />
                </Trigger>
                <Trigger Property="AlternationIndex" Value="1" >
                    <Setter Property="Background" Value="#f2f2f2" />
                </Trigger>

                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="LightGray"/>
                    <!--<Setter Property="Foreground" Value="White"/>-->
                </Trigger>

                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Foreground" Value="Black"/>
                </Trigger>
            </Style.Triggers>
        </Style>
        <!--单元格样式触发-->
        <Style TargetType="DataGridCell">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="DataGridCell">
                        <TextBlock TextAlignment="Center" VerticalAlignment="Center"  >
                    <ContentPresenter />
                        </TextBlock>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Foreground" Value="Black"/>
                </Trigger>
            </Style.Triggers>
        </Style>

        <Style TargetType="DataGrid" x:Key="DataGridStyle1">
            <!--  网格线颜色  -->
            <Setter Property="RowHeaderWidth" Value="0" />
            <Setter Property="BorderThickness" Value="{StaticResource DataGrid.BorderThickness}" />
            <Setter Property="HeadersVisibility" Value="Column" />
            <Setter Property="Background" Value="{StaticResource ColumnHeader.Background}" />
            <Setter Property="BorderBrush" Value="{StaticResource DataGrid.BorderBrush}" />
            <Setter Property="HorizontalGridLinesBrush" Value="#00E9ECF1" />
            <Setter Property="VerticalGridLinesBrush" Value="#00E9ECF1" />
            <Setter Property="UseLayoutRounding" Value="True" />
            <Setter Property="SnapsToDevicePixels" Value="True" />
            <Setter Property="AutoGenerateColumns" Value="False" />
            <Setter Property="CanUserAddRows" Value="False" />
            <Setter Property="CanUserReorderColumns" Value="False" />
            <Setter Property="CanUserResizeColumns" Value="False" />
            <Setter Property="CanUserResizeRows" Value="False" />
            <Setter Property="CanUserSortColumns" Value="False" />
            <Setter Property="GridLinesVisibility" Value="None" />
            <Setter Property="IsReadOnly" Value="True" />
            <Setter Property="RowHeight" Value="{StaticResource DataGridRow.Height}" />
            <Setter Property="SelectionMode" Value="Single" />
        </Style>
    </Window.Resources>
    <Grid>
        <!--当前托盘采集数据列表分页显示面板-->
        <Border Grid.Row="3" BorderThickness="1"
BorderBrush="Gray"
CornerRadius="5" Margin="8"
Background="Transparent">
            <Grid Margin="5">
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="30"/>
                </Grid.RowDefinitions>
                <DataGrid Background="Transparent" HorizontalScrollBarVisibility="Disabled" 
    ItemsSource="{Binding ViewSource}" AutoGenerateColumns="false" Margin="2" Style="{StaticResource DataGridStyle1}">
                    <DataGrid.Columns>
                        <DataGridTextColumn Binding="{Binding Id}" Header="序号" Width="80"/>
                        <DataGridTextColumn Binding="{Binding Name}" Header="姓名" Width="100"/>
                        <DataGridTextColumn Binding="{Binding Gender}" Header="性别" Width="80"/>
                        <DataGridTextColumn Binding="{Binding Age}" Header="年龄" Width="80"/>
                        <DataGridTextColumn Binding="{Binding Email}" Header="邮箱" Width="*"/>
                        <DataGridTextColumn Binding="{Binding Phone}" Header="手机号" Width="*"/>
                    </DataGrid.Columns>
                </DataGrid>
                <uc:DataPager Grid.Row="1" HorizontalAlignment="Right"  PageIndex="{Binding PageIndex, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
          PageSize="{Binding PageSize, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
          TotalCount="{Binding TotalCount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
            </Grid>
        </Border>
    </Grid>
</Window>

本文把DataGrid 的属性参数提取出来放在全局配置中。如下所示:

 <Application.Resources>
     <ResourceDictionary>

     <!--界面边框-->
     <SolidColorBrush x:Key="Border.BorderBrush" Color="#50F150" />

     <sys:Double x:Key="DataGridRow.Height">33</sys:Double>
     <!--  表格外边框线粗细,一般不修改  -->
     <Thickness x:Key="DataGrid.BorderThickness" Bottom="1" Left="1" Right="1" Top="1"/>
     <!--  行边框粗细,一般不修改  -->
     <Thickness x:Key="DataGridRow.BorderThickness" Bottom="0" Left="0" Right="0" Top="1"/>
     <!--  表格外边框颜色  -->
     <SolidColorBrush x:Key="DataGrid.BorderBrush" Color="#E9ECF1" />
     <!--  列头背景色  -->
     <SolidColorBrush x:Key="ColumnHeader.Background" Color="#F6F7FB" />
     <!--  列头边框颜色  -->
     <SolidColorBrush x:Key="ColumnHeader.BorderBrush" Color="#E9ECF1" />

     <vm:ViewModelLocator xmlns:vm="clr-namespace:Wpf_Examples.ViewModels" x:Key="Locator"></vm:ViewModelLocator>
     </ResourceDictionary>
 </Application.Resources>

PageBarViewModel.cs 代码实现如下:

using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using Wpf_Examples.Models;

namespace Wpf_Examples.ViewModels
{
    public class PageBarViewModel:ObservableObject
    {
        #region 字段
        public ICollectionView ViewSource { set; get; }
        int showDataCount = 0;

        #endregion

        #region 属性
        /// <summary>
        /// 分页页序号
        /// </summary>
        private int pageIndex = 1;
        public int PageIndex
        {
            get { return pageIndex; }
            set { SetProperty(ref pageIndex, value); RefreshView(); }
        }
        /// <summary>
        /// 分页每页显示数据条数
        /// </summary>
        private int pageSize;
        public int PageSize
        {
            get { return pageSize; }
            set { SetProperty(ref pageSize, value); RefreshView(); }
        }
        /// <summary>
        /// 总显示数据条数
        /// </summary>
        private int totalCount = 0;
        public int TotalCount
        {
            get { return totalCount; }
            set { SetProperty(ref totalCount, value); }
        }
        /// <summary>
        /// 需要显示的数据集合
        /// </summary>
        private ObservableCollection<DataInfoListModel> dataInfoList = new ObservableCollection<DataInfoListModel>();
        public ObservableCollection<DataInfoListModel> DataInfoList
        {
            get { return dataInfoList; }
            set { SetProperty(ref dataInfoList, value); }
        }



        #endregion

        public PageBarViewModel()
        {
            Random random = new Random();
            for (int i = 0; i < 30; i++)
            {
                DataInfoListModel dataInfoListModel = new DataInfoListModel();
                dataInfoListModel.Order = (i + 1);
                dataInfoListModel.Id = (i + 1); 
                dataInfoListModel.Name = "测试"+(i+1)+"号";
                dataInfoListModel.Gender = "男";
                dataInfoListModel.Age = random.Next(10,80);
                dataInfoListModel.Phone = "17455861459";
                dataInfoListModel.Email = "1453849257@qq.com";
                DataInfoList.Add(dataInfoListModel);
            }
            TotalCount = DataInfoList.Count;
            ViewSource = CollectionViewSource.GetDefaultView(DataInfoList);
            ViewSource.Filter = new Predicate<object>(OnFilterMovie);
        }


        private void RefreshView()
        {
            showDataCount = 0;
            ViewSource.Refresh();
        }

        /// <summary>
        /// 数据过滤器
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private bool OnFilterMovie(object obj)
        {
            if (DataInfoList.Count == 0) return false;
            if (showDataCount >= pageSize) return false;
            if (!(obj is DataInfoListModel info)) return false;
            bool flag = UserControlLib.Actions.PageBarAction.GetDataByPage(pageSize, PageIndex, DataInfoList.ToList(), info);
            if (flag) showDataCount++;
            return flag;
        }

    }
}

3、运行效果

在这里插入图片描述

4、源代码获取

CSDN下载链接:WPF+MVVM案例实战(六)- 自定义分页控件实现


http://www.kler.cn/news/367160.html

相关文章:

  • DEVOPS: 容器与虚拟化与云原生
  • 2024软考网络工程师笔记 - 第8章.网络安全
  • 基于SSM考研助手系统的设计
  • 地平线x5下运行yolo11s-seg模型
  • 边缘计算路由网关R40钡铼技术3LAN口1WAN口Modbus协议
  • 开源模型应用落地-LangChain实用小技巧-带阈值的相似性搜索(十五)
  • 华为网络管理配置实例
  • [Ansible实践笔记]自动化运维工具Ansible(一):初探ansibleansible的点对点模式
  • TensorFlow面试整理-TensorFlow 基础概念
  • JavaScript part2
  • jenkins 作业添加用户权限
  • 练习LabVIEW第十八题
  • 在xml 中 不等式 做转义处理的问题
  • Nginx16-Lua扩展案例
  • Django从请求到响应
  • 阿里云镜像源无法访问?使用 DaoCloud 镜像源加速 Docker 下载(Linux 和 Windows 配置指南)
  • ESP32-S3学习笔记:常用的ESP-IDF命令总结
  • Junit + Mockito保姆级集成测试实践
  • 尚硅谷-react教程-求和案例-@redux-devtools/extension 开发者工具使用-笔记
  • 2分钟搞定 HarmonyOs Next创建模拟器
  • 4.1.2 网页设计技术
  • 【Vue3】基于 Vue3 + ECharts 实现北京市区域地图可视化
  • python网络爬虫基础:URL的组成与结构
  • HTTP错误代码解决详解
  • 手写数据库连接池---C++11(上)
  • vue3+vite 部署npm 包