zoukankan      html  css  js  c++  java
  • 分页控件设计

    分页控件设计

    最近要求项目组成员开发一个通用的分页组件,要求是这个组件简单易用,通用性,兼容现有框架MVVM模式,可是最后给我提交的成果勉强能够用,却欠少灵活性和框架兼容性。

    设计的基本思想:传入数据源,总页数,当前页码,每页记录数,达到分页显示数据的功能

    我把原本不支持MVVM的源码改善了一下,可能还可以再优化得好些,支持MVVM模式,较果如下图:

    image

    添加一解决方案:TLAgent.Pager

    image

    • 设计DataPager类,继承UserControl, INotifyPropertyChanged ,参考如下代码:
    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.ComponentModel;
    
    namespace TLAgent.Pager {
        /// <summary>
        /// DataPager.xaml 的交互逻辑
        /// </summary>
        public partial class DataPager : UserControl, INotifyPropertyChanged {
            public DataPager() {
                InitializeComponent();
            }
    
            #region 依赖属性和事件
            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(10));
    
    
    
            public int Total {
                get { return (int)GetValue(TotalProperty); }
                set { SetValue(TotalProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for Total.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty TotalProperty =
                DependencyProperty.Register("Total", typeof(int), typeof(DataPager), new UIPropertyMetadata(0));
    
    
    
            public int PageIndex {
                get { return (int)GetValue(PageIndexProperty); }
                set { SetValue(PageIndexProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for PageIndex.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty PageIndexProperty =
                DependencyProperty.Register("PageIndex", typeof(int), typeof(DataPager), new UIPropertyMetadata(1));
    
    
    
            public string PageSizeList {
                get { return (string)GetValue(PageSizeListProperty); }
                set { SetValue(PageSizeListProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for PageSizeList.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty PageSizeListProperty =
                DependencyProperty.Register("PageSizeList", typeof(string), typeof(DataPager), new UIPropertyMetadata("5,10,20", (s, e) => {
                    DataPager dp = s as DataPager;
                    if (dp.PageSizeItems == null) dp.PageSizeItems = new List<int>();
                    else dp.PageSizeItems.Clear();
                    dp.RaisePropertyChanged("PageSizeItems");
                }));
    
            public  IEnumerable<object> ItemsSource {
                get { return (IEnumerable<object>)GetValue(ItemsSourceProperty); }
                set { SetValue(ItemsSourceProperty, value); }
            }
    
            /// <summary>
            /// ItemsSource数据源
            /// </summary>
            public static DependencyProperty ItemsSourceProperty =
                DependencyProperty.Register("ItemsSource", typeof(IEnumerable<object>), typeof(DataPager), new UIPropertyMetadata(null));
    
    
    
            public static readonly RoutedEvent PageChangedEvent = EventManager.RegisterRoutedEvent("PageChanged", RoutingStrategy.Bubble, typeof(PageChangedEventHandler), typeof(DataPager));
            /// <summary>
            /// 分页更改事件
            /// </summary>
            public event PageChangedEventHandler PageChanged {
                add {
                    AddHandler(PageChangedEvent, value);
                }
                remove {
                    RemoveHandler(PageChangedEvent, value);
                }
            }
            #endregion
            public ICommand PageChangedCommand { get; set; }
    
            #region 通知属性
            private List<int> _pageSizeItems;
            /// <summary>
            /// 显示每页记录数集合
            /// </summary>
            public List<int> PageSizeItems {
                get {
                    if (_pageSizeItems == null) {
                        _pageSizeItems = new List<int>();
                    }
                    if (PageSizeList != null) {
                        List<string> strs = PageSizeList.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                        _pageSizeItems.Clear();
                        strs.ForEach(c => {
                            _pageSizeItems.Add(Convert.ToInt32(c));
                        });
                    }
                    return _pageSizeItems;
                }
                set {
                    if (_pageSizeItems != value) {
                        _pageSizeItems = value;
                        RaisePropertyChanged("PageSizeItems");
                    }
                }
            }
    
            private int _pageCount;
            /// <summary>
            /// 总页数
            /// </summary>
            public int PageCount {
                get { return _pageCount; }
                set {
                    if (_pageCount != value) {
                        _pageCount = value;
                        RaisePropertyChanged("PageCount");
                    }
                }
            }
    
            private int _start;
            /// <summary>
            /// 开始记录数
            /// </summary>
            public int Start {
                get { return _start; }
                set {
                    if (_start != value) {
                        _start = value;
                        RaisePropertyChanged("Start");
                    }
                }
            }
    
            private int _end;
            /// <summary>
            /// 结束记录数
            /// </summary>
            public int End {
                get { return _end; }
                set {
                    if (_end != value) {
                        _end = value;
                        RaisePropertyChanged("End");
                    }
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
            public void RaisePropertyChanged(string propertyName) {
                if (PropertyChanged != null) {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
            #endregion
    
            #region 字段、属性、委托
            public delegate void PageChangedEventHandler(object sender, PageChangedEventArgs args);
            private PageChangedEventArgs pageChangedEventArgs; 
            #endregion
    
    
    
            #region 引发分页更改事件
            /// <summary>
            /// 引发分页更改事件
            /// </summary>
            private void RaisePageChanged() {
                if (pageChangedEventArgs == null) {
                    pageChangedEventArgs = new PageChangedEventArgs(PageChangedEvent, PageSize, PageIndex);
                } else {
                    pageChangedEventArgs.PageSize = this.PageSize;
                    pageChangedEventArgs.PageIndex = this.PageIndex;
                }
                RaiseEvent(pageChangedEventArgs);
                //calc start、end
                if (ItemsSource != null) {
                    int curCount = ItemsSource.Count();
                    Start = (PageIndex - 1) * PageSize + 1;
                    End = Start + curCount - 1;
    
                    if (Total % PageSize != 0) {
                        PageCount = Total / PageSize + 1;
                    } else {
                        PageCount = Total / PageSize;
                    }
                } else {
                    Start = End = PageCount = Total = 0;
                }
    
                //调整图片的显示
                btnFirst.IsEnabled = btnPrev.IsEnabled = (PageIndex != 1);
                btnNext.IsEnabled = btnLast.IsEnabled = (PageIndex != PageCount);
            } 
            #endregion
    
            #region 分页操作事件
            void DataPager_Loaded(object sender, RoutedEventArgs e) {
                RaisePageChanged();
            }
    
            private void cbpPageSize_SelectionChanged(object sender, SelectionChangedEventArgs e) {
                if (this.IsLoaded) {
                    PageSize = (int)cboPageSize.SelectedItem;
                    RaisePageChanged();
                }
            }
    
            private void btnFirst_Click(object sender, RoutedEventArgs e) {
                PageIndex = 1;
                RaisePageChanged();
            }
    
            private void btnPrev_Click(object sender, RoutedEventArgs e) {
                if (PageIndex > 1) {
                    --PageIndex;
                }
                RaisePageChanged();
            }
    
            private void btnNext_Click(object sender, RoutedEventArgs e) {
                if (Total % PageSize != 0) {
                    PageCount = Total / PageSize + 1;
                } else {
                    PageCount = Total / PageSize;
                }
    
                if (PageIndex < PageCount) {
                    ++PageIndex;
                }
                RaisePageChanged();
            }
    
            private void btnLast_Click(object sender, RoutedEventArgs e) {
                if (Total % PageSize != 0) {
                    PageCount = Total / PageSize + 1;
                } else {
                    PageCount = Total / PageSize;
                }
                PageIndex = PageCount;
                RaisePageChanged();
            }
            private void btnRefresh_Click(object sender, RoutedEventArgs e) {
                RaisePageChanged();
            }
    
            private void tbPageIndex_PreviewKeyDown(object sender, KeyEventArgs e) {
                if (e.Key == Key.Enter) {
                    tbPageIndex_LostFocus(sender, null);
                }
            }
    
            private void tbPageIndex_LostFocus(object sender, RoutedEventArgs e) {
                int pIndex = 0;
                try {
                    pIndex = Convert.ToInt32(tbPageIndex.Text);
                } catch { pIndex = 1; }
    
                if (pIndex < 1) PageIndex = 1;
                else if (pIndex > PageCount) PageIndex = PageCount;
                else PageIndex = pIndex;
    
                RaisePageChanged();
            } 
            #endregion
    
            
    
            
        }
    
        /// <summary>
        /// 分页更改参数
        /// </summary>
        public class PageChangedEventArgs : RoutedEventArgs {
            public int PageSize { get; set; }
            public int PageIndex { get; set; }
    
            public PageChangedEventArgs(RoutedEvent routeEvent, int pageSize, int pageIndex)
                : base(routeEvent) {
                this.PageSize = pageSize;
                this.PageIndex = pageIndex;
            }
        }
    }
    复制代码
    • 添加一支持泛型类,可以传入任何类型对象
    复制代码
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    
    namespace TLAgent.Pager
    {
        public class DataResult<T> : INotifyPropertyChanged
        {
    
            public int _total;
            public int Total
            {
                get
                {
                    return _total;
                }
                set
                {
                    if (_total != value)
                    {
                        _total = value;
                        RaisePropertyChanged("Total");
                    }
                }
            }
    
            private List<T> _dataSource;
            public List<T> DataSource
            {
                get
                {
                    return _dataSource;
                }
                set
                {
                    if (_dataSource != value)
                    {
                        _dataSource = value;
                        RaisePropertyChanged("DataSource");
                    }
                }
            }
    
            public DataResult()
            {
                DataSource = new List<T>();
            }
    
            public void RaisePropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
        }
    }
    复制代码

    添加一个测试项目:TLAgent.Pager.Test

    image

    • 自定义一个命令InteractiveCommand,支持传入参数,代码参考:
    复制代码
    // -----------------------------------------------------------------------
    // <copyright file="InteractiveCommand.cs" company="M&M">
    // TODO: Update copyright text.
    // </copyright>
    // -----------------------------------------------------------------------
    
    namespace TLAgent.Pager.Test
    {
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;
        using System.Windows;
        using System.Windows.Input;
        using System.Windows.Interactivity;
        using System.Reflection;
    
        /// <summary>
        /// TODO: Update summary.
        /// </summary>
        public class InteractiveCommand : TriggerAction<DependencyObject>
        {
            protected override void Invoke(object parameter)
            {
                if (base.AssociatedObject != null)
                {
                    ICommand command = this.ResolveCommand();
                    object[] tempObj = { parameter, CommandParameter };
                    if ((command != null) && command.CanExecute(tempObj))
                    {
                        command.Execute(tempObj);
                    }
                }
            }
    
            public object CommandParameter
            {
                get { return GetValue(CommandParameterProperty); }
                set { SetValue(CommandParameterProperty, value); }
            }
    
            public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register
                ("CommandParameter", typeof(object), typeof(InteractiveCommand), new PropertyMetadata(null, OnCommandParameterChanged));
    
            private static void OnCommandParameterChanged
                (DependencyObject sender, DependencyPropertyChangedEventArgs e)
            {
                InteractiveCommand ic = sender as InteractiveCommand;
                if (ic != null)
                {
                    ic.SynchronizeElementState();
                }
            }
    
            private void SynchronizeElementState()
            {
                ICommand command = Command;
                if (command != null)
                {
                    FrameworkElement associatedObject = AssociatedObject as FrameworkElement;
                    if (associatedObject != null)
                    {
                        associatedObject.IsEnabled = command.CanExecute(CommandParameter);
                    }
                }
            }
    
            private ICommand ResolveCommand()
            {
                ICommand command = null;
                if (this.Command != null)
                {
                    return this.Command;
                }
                if (base.AssociatedObject != null)
                {
                    foreach (PropertyInfo info in base.AssociatedObject.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
                    {
                        if (typeof(ICommand).IsAssignableFrom(info.PropertyType) && string.Equals(info.Name, this.CommandName, StringComparison.Ordinal))
                        {
                            command = (ICommand)info.GetValue(base.AssociatedObject, null);
                        }
                    }
                }
                return command;
            }
    
            private string commandName;
            public string CommandName
            {
                get
                {
                    base.ReadPreamble();
                    return this.commandName;
                }
                set
                {
                    if (this.CommandName != value)
                    {
                        base.WritePreamble();
                        this.commandName = value;
                        base.WritePostscript();
                    }
                }
            }
    
            #region Command
            public ICommand Command
            {
                get { return (ICommand)GetValue(CommandProperty); }
                set { SetValue(CommandProperty, value); }
            }
            public static readonly DependencyProperty CommandProperty =
                DependencyProperty.Register("Command", typeof(ICommand), typeof(InteractiveCommand), new UIPropertyMetadata(null));
            #endregion
    
        }
    }
    复制代码

    在MainWindow.xaml中,添一DataGrid和一个DataPager,参考如下代码:

    复制代码
    <Window x:Class="TLAgent.Pager.Test.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:lib="clr-namespace:TLAgent.Pager;assembly=TLAgent.Pager"
            xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
            xmlns:cmd="clr-namespace:TLAgent.Pager.Test" 
            xmlns:viewModels="clr-namespace:TLAgent.Pager.Test.ViewModels"
            Name="self"
            Title="MainWindow" Height="350" Width="525">
        <Window.DataContext>
            <viewModels:MainWindowViewModel/>
        </Window.DataContext>
    
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <DataGrid ItemsSource="{Binding Path=ItemsSource,ElementName=dataPager}">
                <!--<DataGrid.Columns>
                    <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
                    <DataGridTextColumn Header="Age" Binding="{Binding Age}" />
                    <DataGridTextColumn Header="Gender" Binding="{Binding Gender}" />
                </DataGrid.Columns>-->
            </DataGrid>
            <lib:DataPager Grid.Row="1" Name="dataPager" PageSizeList="10,20,30,50" 
                           ItemsSource="{Binding Result.DataSource,Mode=TwoWay}"
                           Total="{Binding Result.Total,Mode=TwoWay}" 
                >
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="PageChanged">
                        <cmd:InteractiveCommand Command="{Binding PageChangedCommand}" CommandName="PageChangedCommand"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
    
            </lib:DataPager>
        </Grid>
    </Window>
    复制代码

    添加一个ViewModel:MainWindowViewModel,继承NotificationObject:

    复制代码
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Input;
    using Microsoft.Practices.Prism.Commands;
    using Microsoft.Practices.Prism.ViewModel;
    
    namespace TLAgent.Pager.Test.ViewModels
    {
        public class MainWindowViewModel : NotificationObject
        {
    
            private DelegateCommand<object[]> _commandWithEventArgs;
            public List<Student> _dataSource;//声明数据
     
            public MainWindowViewModel()
            {
                Result = new DataResult<Student>();//此处Student可以传入任何数据类型
                _dataSource = Controller.GetData();//获取得数据
                Result.DataSource = _dataSource;//给数据源赋值
                Query(10, 1);
            }
    
            private DataResult<Student> _result;
            public DataResult<Student> Result//公开给View作数据源绑定
            {
                get { return _result; }
    
                set
                {
                    _result = value;
                    RaisePropertyChanged("Result");
                }
            }
    
            public void Query(int size, int pageIndex)
            {
                Result.Total = _dataSource.Count;//给页总数赋值
                Result.DataSource = _dataSource.Skip((pageIndex - 1) * size).Take(size).ToList();//改变数据源赋值
            }
            /// <summary>
            /// 
            /// </summary>
            public ICommand PageChangedCommand
            {
                get { return _commandWithEventArgs ?? (_commandWithEventArgs = new DelegateCommand<object[]>(ShowData)); }
            }
    
            private void ShowData(object[] objParam)
            {
                PageChangedEventArgs args = (PageChangedEventArgs)objParam[0];//View把PageChangedEventArgs事件传过来,此事件带来页码和页序号
                Query(args.PageSize, args.PageIndex);
            }
        }
    }
    复制代码

    添加一个Controller类,从此类中获取测试数据来源:

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace TLAgent.Pager.Test
    {
        public class Controller
        {
    
            public static List<Student> GetData()
            {
                List<Student> Students;
                Students = new List<Student>();
    
                Random random = new Random();
                int count = random.Next(20, 200);
                for (int i = 1; i <= count; i++)
                {
                    Student stu = new Student
                    {
                        Name = "Name" + i,
                        Age = random.Next(20, 50),
                        Gender = (i % 3 != 0),
                        Desc = "Desc " + i,
                    };
                    Students.Add(stu);
                }
                return Students;
            } 
        }
    }
    复制代码

    添加一个Student类,只是作为测试用,项目中可以按实际需要,DataResult<T>是支持多种类型的数据。

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Practices.Prism.ViewModel;
    
    namespace TLAgent.Pager.Test {
        public class Student : NotificationObject
        {
            public string Name { get; set; }
            public int Age { get; set; }
            public bool Gender { get; set; }
            public string Desc { get; set; }
        }
    }
    复制代码

           到此一个分页控件设计就完成了,在此做一些总结。

          源码

     
     
  • 相关阅读:
    jquery另外一种类似tab切换效果
    简单的Tab切换组件
    switchable图片切换
    web前端性能优化总结
    iframe之间通信问题及iframe自适应高度问题
    javascript cookie
    grunt项目构建工具
    input全选与单选(把相应的value放入隐藏域去)
    Ajax跨域问题
    Jquery回到顶部功能
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3309459.html
Copyright © 2011-2022 走看看