wpf研究之道——datagrid控件分页

         datagrid控件分页效果,如下图所示:

        

        上一页,下一页,可以跳到任何一页。当页码比较多的时候,只显示几页,其余用点点,界面实现如下:

 <!--分页-->
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Top"  Grid.Row="2" Margin="0 20"  x:Name="fulltextPager">

            <Button x:Name="prePage" Click="prePage_Click" Style="{StaticResource btnPager}" ToolTip="上一页"/>

            <Button Style="{StaticResource btnPager}"  Content="1" x:Name="bntGoFirstPage"  Click="bntGoFirstPage_Click" />


            <TextBlock x:Name="predot" Text="..." Visibility="{Binding PreVisible}"/>

            <ItemsControl ItemsSource="{Binding Pages}" x:Name="btnPagerContainer">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <WrapPanel>
                            <Button Style="{StaticResource btnPager}"  Content="{Binding Name}"  Click="btn_GotoPage" />
                        </WrapPanel>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
                <!--这里用WrapPanel 当容器放Button-->
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>

                        <WrapPanel Orientation="Horizontal"/>

                    </ItemsPanelTemplate>

                </ItemsControl.ItemsPanel>

            </ItemsControl>

            <TextBlock x:Name="nextdot" Text="..." Visibility="{Binding NextVisible}"/>

            <Button Style="{StaticResource btnPager}"  Content="{Binding Total}" x:Name="btnGoLastPage"  Click="btnGoLastPage_Click" />


            <Button x:Name="nextPage" Click="nextPage_Click" Content=">>" Style="{StaticResource btnPager}"  ToolTip="下一页"/>

            <TextBlock Text="当前"/>
            <TextBlock Text="{Binding PageIndex}" Foreground="#3091f2"/>
            <TextBlock Text=""/>

            <TextBlock Text="跳转到" Style="{StaticResource pagerStyle}" Margin="5 0 5 0"/>
            <TextBox x:Name="wantToGo" Width="50" Height="25"></TextBox>
            <TextBlock Text="" Style="{StaticResource pagerStyle}"/>

            <TextBlock Style="{StaticResource pagerStyle}">

               <Button Content="go" x:Name="goPage"  Click="goPage_Click" Style="{StaticResource btnPager}" />

            </TextBlock>

            <TextBlock Style="{StaticResource pagerStyle}">

                             <TextBlock Text=""/>
                             <TextBlock Text="{Binding ItemCount}" Foreground="#3091f2"/>
                             <TextBlock Text=""/>
                 
          </TextBlock>

        </StackPanel>

         ItemsControl 是一个完全自定义的集合控件,它没有默认的形状,不像button,它默认为长方形。看看它的数据是如何绑定的?

         this 代表了TestCaseUserControl ,这是个自定义的用户控件,它里面包含了datagrid控件以及分页。Data是个复杂的对象,包含了数据源以及一些分页支持。

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;

namespace WpfReovlveTest
{
    public class PageDataManager<T> : INotifyPropertyChanged
    {
        private int pageSize = 10;
        public int PageSize
        {
            get { return pageSize; }
            set
            {
                pageSize = value;
                NotifyPropertyChanged("PageSize");
            }
        }

        private int pageIndex;
        public int PageIndex
        {
            get { return pageIndex; }
            set
            {
                pageIndex = value;
                NotifyPropertyChanged("PageIndex");
            }
        }

        private int total;
        public int Total
        {
            get { return total; }
            set
            {
                total = value;
                NotifyPropertyChanged("Total");
            }
        }

        private Visibility preVisible = Visibility.Collapsed;

        public Visibility PreVisible
        {
            get { return preVisible; }
            set
            {
                preVisible = value;
                NotifyPropertyChanged("PreVisible");
            }
        }


        private Visibility nextVisible = Visibility.Collapsed;

        public Visibility NextVisible
        {
            get { return nextVisible; }
            set
            {
                nextVisible = value;
                NotifyPropertyChanged("NextVisible");
            }
        }


        private ObservableCollection<Pages> pages;
        public ObservableCollection<Pages> Pages
        {
            get { return pages; }
            set
            {
                pages = value;
                NotifyPropertyChanged("Pages");
            }
        }
        /// <summary>
        /// 总数
        /// </summary>
        private int itemCount;
        public int ItemCount
        {
            get { return itemCount; }
            set
            {
                itemCount = value;
                NotifyPropertyChanged("ItemCount");
            }
        }



        private ObservableCollection<T> dataSource;

        /// <summary>
        /// 总的数据源
        /// </summary>
        public ObservableCollection<T> DataSource
        {
            get { return dataSource; }
            set
            {
                dataSource = value;
                NotifyPropertyChanged("DataSource");
            }
        }

        private ObservableCollection<T> pagerSource = new ObservableCollection<T>();

        /// <summary>
        /// 每页的数据源
        /// </summary>
        public ObservableCollection<T> PagerSource
        {
            get { return pagerSource; }
            set
            {
                pagerSource = value;
                NotifyPropertyChanged("PagerSource");
            }
        }

        public Action<int, int> PagerOp;

        public bool IsMemoryPager { set; get; }


        //负责监视属性的变化
        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged(string Propertyname)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(Propertyname));
            }
        }

        /// <summary>
        /// 打开等待窗口
        /// </summary>
        public Action OpenWaitingWindow { set; get; }
        /// <summary>
        /// 关闭等待窗口
        /// </summary>
        public Action CloseWaitingWindow { set; get; }

        public UIElement Owner { get; set; }

        public PageDataManager(ObservableCollection<T> source, int count, bool isMemoryPager = true, Action<int, int> PagerOp = null, int pageSize = 10, int pageIndex = 1)
        {
            this.PageSize = pageSize;
            this.DataSource = source;
            this.ItemCount = count;
            this.Total = this.ItemCount % PageSize == 0 ? ItemCount / PageSize : ItemCount / PageSize + 1;

            this.PagerOp = PagerOp;

            this.PageIndex = pageIndex;

            this.IsMemoryPager = isMemoryPager;

            Pager(this.PageIndex, false);
        }

        private void MakePagerNum()
        {
            //初始化页数数组
            if (this.Pages == null)
            {
                this.Pages = new ObservableCollection<Pages>();
            }
            else
            {
                this.Pages.Clear();
            }

            this.PreVisible = Visibility.Collapsed;
            this.NextVisible = Visibility.Collapsed;

            if (this.Total > 7)
            {
                //以当前页为分界点,向左借2个,向右借2个

                int leftLength = this.PageIndex - 1;
                int rightLength = this.Total - this.PageIndex;

                if (leftLength > 3 && rightLength > 3)
                {
                    this.PreVisible = Visibility.Visible;

                    for (int i = PageIndex - 2; i <= PageIndex + 2; i++)
                    {
                        this.Pages.Add(new Pages() { Name = i.ToString(), PageIndex = i });
                    }
                    this.NextVisible = Visibility.Visible;
                }

                if (rightLength <= 3)
                {
                    //右边的不够,向左边借
                    this.PreVisible = Visibility.Visible;

                    for (int i = this.PageIndex - (5 - rightLength); i <= this.Total - 1; i++)
                    {
                        this.Pages.Add(new Pages() { Name = i.ToString(), PageIndex = i });
                    }
                }
                if (leftLength <= 3)
                {
                    //左边的不够,向右边借
                    for (int i = 2; i <= this.PageIndex + (5 - leftLength); i++)
                    {
                        this.Pages.Add(new Pages() { Name = i.ToString(), PageIndex = i });
                    }
                    this.NextVisible = Visibility.Visible;
                }
            }
            else
            {
                for (int i = 2; i <= Total - 1; i++)
                {
                    this.Pages.Add(new Pages() { Name = i.ToString(), PageIndex = i });
                }
            }
        }

        private void PagerOpCompleted(IAsyncResult result)
        {
            try
            {
                var handler = (Action<int, int>)((AsyncResult)result).AsyncDelegate;
                handler.EndInvoke(result);

                if (this.Owner != null)
                {
                    this.Owner.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                               (ThreadStart)delegate()
                               {
                                   FillPagerSource();
                               });
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("异步分页出错:" + ex.Message);
            }
            finally
            {
                //关闭等待图标
                if (this.Owner != null)
                {
                    this.Owner.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                                 (ThreadStart)delegate()
                                 {
                                     if (CloseWaitingWindow != null)
                                     {
                                         CloseWaitingWindow();
                                     }
                                 });
                }
            }
        }
        public void Pager(int pageIndex, bool canPager = true)
        {
            if (pageIndex < 1 || pageIndex > this.Total)
            {
                return;
            }
            this.PageIndex = pageIndex;

            MakePagerNum();

            if (PagerOp != null && canPager)
            {
                //委托异步执行

                IAsyncResult result = PagerOp.BeginInvoke(this.PageSize, pageIndex, new AsyncCallback(PagerOpCompleted), null);

                //打开等待图标

                if (OpenWaitingWindow != null)
                {
                    OpenWaitingWindow();
                }
            }
            else
            {
                FillPagerSource();
            }
        }

        private void FillPagerSource()
        {
            IEnumerable<T> pagerDatas = DataSource;

            if (this.IsMemoryPager)
            {
                List<T> tempSource = new List<T>();
                tempSource.AddRange(this.DataSource);
                pagerDatas = tempSource.Skip((this.PageIndex - 1) * PageSize).Take(this.PageSize);
            }

            this.PagerSource.Clear();

            foreach (var item in pagerDatas)
            {
                this.PagerSource.Add(item);
            }
        }
    }
}

public class Pages
{
    public string Name { get; set; }
    public int PageIndex { get; set; }
}
分页类

         这是一个通用的wpf分页类,即可用给datagrid使用,也可以给ListView使用。使用方法如下:

        public void SetSource(ObservableCollection<TestCaseListViewModel> models, int itemCount, bool isMemoryPager, int pageIndex = 1)
        {
            this.FullTextList = models;
            this.Data = new PageDataManager<TestCaseListViewModel>(FullTextList, itemCount, isMemoryPager, this.PagerFullTask, PageSize, pageIndex);

            this.Data.OpenWaitingWindow = OpenWaitingWindow;
            this.Data.CloseWaitingWindow = CloseWaitingWindow;
            this.Data.Owner = this;

            this.DataContext = Data;
            this.TestCaseDataGrid.DataContext = Data.PagerSource;

            fulltextPager.Visibility = itemCount == 0 ? Visibility.Collapsed : Visibility.Visible;

            prePage.Content = "<<";
            btnGoLastPage.Visibility = Data.Total == 1 ? System.Windows.Visibility.Collapsed : System.Windows.Visibility.Visible;

        }

       在自定义的用户控件中,实例化分页类,参数说明如下:

      FullTextList:数据源

      itemCount:总数

      isMemoryPager:是否内存分页(false:数据库分页)

     PagerFullTask:获取每页数据源的方法

    这个数据分页类与具体的控件无关,它只与数据源相关。

posted @ 2018-04-08 11:44  micDavid  阅读(1693)  评论(0编辑  收藏  举报