zoukankan      html  css  js  c++  java
  • 自定义WPF分页控件

    一、分页控件功能说明

    image-20210518195232122

    实现如上图所示的分页控件,需要实现一下几个功能:

    1. 可以设置每页能够展示的最大列数(例如每页8列、每页16列等等)。
    2. 加载的数组总数量超过设置的每页列数后,需分页展示。
    3. 可以直接点击指定的列数或者上下页按钮进行页面跳转

    二、自定义分页控件使用说明

    为了实现以上功能,主要进行以下工作:

    1、添加一个自定义按钮PagerButton类,声明一个依赖属性IsActive,用于记录当前页面所在页数的按钮,此时该按钮边框高亮显示,具体代码如下:

     public class PagerButton : Button
        {
            public bool IsActive
            {
                get { return (bool)GetValue(IsActiveProperty); }
                set { SetValue(IsActiveProperty, value); }
            }
    
            public static readonly DependencyProperty IsActiveProperty =
                DependencyProperty.Register("IsActive", typeof(bool), typeof(PagerButton), new PropertyMetadata(false));
    
        }
    
      <Style x:Key="PagerButtonStyle" TargetType="controls:PagerButton">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="controls:PagerButton">
                        <Border x:Name="b1" CornerRadius="2" Background="{StaticResource Themes}"
                                                BorderThickness="1" BorderBrush="{StaticResource Disabled}"
                                                Width="32" Height="32" Margin="4,0">
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="b1" Property="BorderBrush" Value="{StaticResource Accent}"></Setter>
                            </Trigger>
                            <Trigger Property="IsActive" Value="True">
                                <Setter TargetName="b1" Property="BorderBrush" Value="{StaticResource Accent}"></Setter>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
            </Style.Triggers>
        </Style>
    

    2、添加自定义分页控件PagerBar类,用于展示分页按钮(使用PagerButton类)和实现分页跳转,需要定义当前页面、总页数、设置的每页最大列数三个依赖属性,具体如下:

       public int CurrentPageIndex
            {
                get { return (int)GetValue(CurrentPageIndexProperty); }
                set { SetValue(CurrentPageIndexProperty, value); }
            }
            public int PageSize
            {
                get { return (int)GetValue(PageSizeProperty); }
                set { SetValue(PageSizeProperty, value); }
            }
            public int PageCount
            {
                get { return (int)GetValue(PageCountProperty); }
                set { SetValue(PageCountProperty, value); }
            }
    
            public static readonly DependencyProperty CurrentPageIndexProperty = DependencyProperty.Register("CurrentPageIndex", typeof(int), typeof(PagerBar), new PropertyMetadata(-1, CurrentPageIndexPropertyChangedCallback));
            public static readonly DependencyProperty PageSizeProperty = DependencyProperty.Register("PageSize", typeof(int), typeof(PagerBar), new PropertyMetadata(10, PageSizePropertyChangedCallback));
            public static readonly DependencyProperty PageCountProperty = DependencyProperty.Register("PageCount", typeof(int), typeof(PagerBar), new PropertyMetadata(-1, PageCountPropertyChangedCallback));
    
    

    3、添加一个工具类Pager,用于将数据按照要求分页,该工具类声明当前页数、总页数、设置的每页最大列数三个属性,具体如下:

      public int PageSize
            {
                get => _pageSize;
                set
                {
                    if (value == _pageSize)
                        return;
                    _pageSize = value;
                    OnPropertyChanged();
                    SetPageSize(_pageSize);
                }
            }
            public int PageCount
            {
                get => _pageCount;
                set
                {
                    if (value == _pageCount)
                        return;
                    _pageCount = value;
    
                    // 最少页为1页
                    if (_pageCount == 0)
                        _pageCount = 1;
                    OnPropertyChanged();
                }
            }
            public int CurPageIndex
            {
                get => _curPageIndex;
                set
                {
                    if (value == _curPageIndex)
                        return;
                    _curPageIndex = value;
                    OnPropertyChanged();
                    GotoPageOf(_curPageIndex);
                }
            }
    

    4、将Pager类和PageBar控件进行数据绑定。具体操作为:在绑定的ViewModel上声明一个Pager类,然后将该Pager类的属性和PagrBar进行一一对应绑定。具体代码如下:

      <controls:PagerBar Grid.Row="1" Margin="5"
                               HorizontalAlignment="Center"
                               PageSize="{Binding Path=Pager.PageSize, Mode=TwoWay}" 
                               PageCount="{Binding Path=Pager.PageCount, Mode=TwoWay}"  
                               CurrentPageIndex="{Binding Path=Pager.CurPageIndex, Mode=TwoWay}"></controls:PagerBar>
    

    5、初始化Pager类时,在界面绑定的ViewModel里面重新声明一个数组,用于保存分页后的数组,将该数组绑定到待展示的条目控件(例如ListBox)上,具体如下:

     StudentCollection=new ObservableCollection<Student>();
                for (int i = 0; i < 10; i++)
                {
                    StudentCollection.Add(new Student()
                    {
                        Id = Index = i,
                        Source = 10 * (i + 1),
                    });
                }
    
                AddCommand =new RelayCommand(ExecuteAddCommand);
                DeleteCommand=new RelayCommand(ExecuteDeleteCommand);
                SortCommand=new RelayCommand(ExecuteSortCommand);
    
                Pager=new Pager<Student>(8,StudentCollection);
                Pager.PagerUpdated += items =>
                {
                    StudentCollectionPaging = new ObservableCollection<Student>(items);
                };
                Pager.CurPageIndex = 1;
    
      <ListBox x:Name="ListBoxStudent" Grid.Row="0"
                     ItemsSource="{Binding StudentCollectionPaging}"
                     ItemTemplate="{StaticResource StudentDateTemplate}"></ListBox>
    

    三、总结说明

    ​ 为了实现绑定的数组添加、删除时,PageBar分组控件也能立即更新控件,Pager工具类增加以下构造函数,首先保证数组为同一引用,其次使用ObservableCollection保证界面和ViewModel即时更新:

        public Pager(int pageSize, ObservableCollection<T> source)
            {
                _pageSize = pageSize;
                _itemsSource = source;
                _itemsSource.CollectionChanged += ItemsSourceOnCollectionChanged;
                CalculatePaging();
            }
    
            private void ItemsSourceOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            {
                CalculatePaging();
                GotoPageOf(CurPageIndex);
            }
    

    四、示例源码

    示例源码地址:分页控件源码

    五、问题

    ​ 在实际应用中,发现如下问题:当需要对绑定的整个数组进行排序时,由于Pager类初始化传入的数组必须和实际数为同一个引用且必须为ObservableCollection数组,那么使用LINQ排序完成后,必须要使用ToList进行转换,就必须重新初始化ObservableCollection,那么后续当该ObservableCollection数组变化时,也无法通知到Pager类的数组了。为了解决该问题,想到以下两个方法:

    (1)自定义排序,针对ObservableCollection的每个数组对象进行排序。这样排序完成后ObservableCollection引用无变化。

    (2)先用临时变量保存排序完成的数组,然后清空ObservableCollection,然后再迭代添加临时数组。如此,ObservableCollection对象前后也为统一引用。

      public ICommand SortCommand { get; set; }
    
            private void ExecuteSortCommand(object obj)
            {
                var list = StudentCollection.ToList().OrderByDescending(item=>item.Source).ToList();
                StudentCollection.Clear();
                foreach (var item in list)
                {
                    StudentCollection.Add(item);
                }
            }
    

    目前暂时采用了第二种方法,但该方法效率不高。后续有更好的解决方法可以留言讨论。

  • 相关阅读:
    动态创建DeepZoom
    MultiSheet Excel Output
    PL/SQL Developer设置技巧
    采购审批专题总结bob
    oracle dbms包和其他包的使用大全
    ARAuto Invoice question
    应收发票相关 脚本
    发运确认停靠站错误
    让R12直接从Form登录
    查找事物处理来源
  • 原文地址:https://www.cnblogs.com/dongweian/p/14782709.html
Copyright © 2011-2022 走看看