• 星空雅梦


    WPF 实现 DataGrid/ListView 分页控件

     

    在WPF中,通常会选用DataGrid/ListView进行数据展示,如果数据量不多,可以直接一个页面显示出来。如果数据量很大,2000条数据,一次性显示在一个页面中,不仅消耗资源,而且用户体验也很糟糕。这篇博客将介绍如何创建一个分页控件。

    为了简单起见,这个分页控件目前只有 首页/上一页/下一页/末页/总页数/第几页 等功能。实现思路,首页/上一页/下一页/末页 这四个通过路由事件来实现,在使用时可以使用命令进行绑定,或者直接使用均可。总页数和第几页通过依赖属性来实现,使用时将页数进行绑定显示即可。示例代码如下:

    Pager控件:

    复制代码
        <UserControl.Resources>
            <Style TargetType="{x:Type Button}">
                <Setter Property="Width" Value="22"/>
                <Setter Property="Height" Value="22"/>
            </Style>
        </UserControl.Resources>
        <Grid>
            <StackPanel Orientation="Horizontal">
                <Button x:Name="FirstPageButton" Margin="5,0" Click="FirstPageButton_Click">
                    <Path Width="7" Height="10" Data="M0,0L0,10 M0,5L6,2 6,8 0,5" Stroke="Black" StrokeThickness="1" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center" />
                </Button>
                <Button x:Name="PreviousPageButton" Margin="0,0,5,0" Click="PreviousPageButton_Click">
                    <Path Width="8" Height="8" Data="M0,4L8,0 8,8z" Stroke="Black" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center" />
                </Button>
                <TextBlock VerticalAlignment="Center">
                    <Run Text="第"/>
                    <Run x:Name="rCurrent" Text="0"/>
                    <Run Text="页"/>
                </TextBlock>
                <Button Margin="5,0" x:Name="NextPageButton" Click="NextPageButton_Click">
                    <Path Width="8" Height="8" Data="M0,4L8,0 8,8z" Stroke="Black" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center">
                        <Path.RenderTransform>
                            <RotateTransform Angle="180" CenterX="4" CenterY="4" />
                        </Path.RenderTransform>
                    </Path>
                </Button>
                <Button Margin="0,0,5,0" x:Name="LastPageButton" Click="LastPageButton_Click">
                    <Path x:Name="MainPath" Width="7" Height="10" Data="M0,0L0,10 M0,5 L6,2 6,8 0,5" Stroke="Black" StrokeThickness="1" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center">
                        <Path.RenderTransform>
                            <RotateTransform Angle="180" CenterX="3" CenterY="5" />
                        </Path.RenderTransform>
                    </Path>
                </Button>
                <TextBlock VerticalAlignment="Center">
                    <Run Text="共"/>
                    <Run x:Name="rTotal" Text="0"/>
                    <Run Text="页"/>
                </TextBlock>
            </StackPanel>     
        </Grid>
    复制代码

    C#:

     View Code

    在MainWindow中,
    XAML:

    复制代码
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
    
            <DataGrid Grid.Row="0" ItemsSource="{Binding FakeSource}" AutoGenerateColumns="False" CanUserAddRows="False">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Item Id" Binding="{Binding Id}" Width="80"/>
                    <DataGridTextColumn Header="Item Name" Binding="{Binding ItemName}" Width="180"/>
                </DataGrid.Columns>
            </DataGrid>
    
            <local:Pager TotalPage="{Binding TotalPage}"
                         CurrentPage="{Binding CurrentPage, Mode=TwoWay}" 
                         HorizontalAlignment="Center"
                         Grid.Row="1">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="FirstPage">
                        <i:InvokeCommandAction Command="{Binding FirstPageCommand}" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="PreviousPage">
                        <i:InvokeCommandAction Command="{Binding PreviousPageCommand}"/>
                    </i:EventTrigger>
                    <i:EventTrigger EventName="NextPage">
                        <i:InvokeCommandAction Command="{Binding NextPageCommand}" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="LastPage">
                        <i:InvokeCommandAction Command="{Binding LastPageCommand}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </local:Pager>
        </Grid>
    复制代码

    MainViewModel类:

    public class MainViewModel : ViewModel
    {
    private ICommand _firstPageCommand;

    public ICommand FirstPageCommand
    {
    get
    {
    return _firstPageCommand;
    }

    set
    {
    _firstPageCommand = value;
    }
    }

    private ICommand _previousPageCommand;

    public ICommand PreviousPageCommand
    {
    get
    {
    return _previousPageCommand;
    }

    set
    {
    _previousPageCommand = value;
    }
    }

    private ICommand _nextPageCommand;

    public ICommand NextPageCommand
    {
    get
    {
    return _nextPageCommand;
    }

    set
    {
    _nextPageCommand = value;
    }
    }

    private ICommand _lastPageCommand;

    public ICommand LastPageCommand
    {
    get
    {
    return _lastPageCommand;
    }

    set
    {
    _lastPageCommand = value;
    }
    }

    private int _pageSize;

    public int PageSize
    {
    get
    {
    return _pageSize;
    }
    set
    {
    if(_pageSize != value)
    {
    _pageSize = value;
    OnPropertyChanged("PageSize");
    }
    }
    }

    private int _currentPage;

    public int CurrentPage
    {
    get
    {
    return _currentPage;
    }

    set
    {
    if(_currentPage != value)
    {
    _currentPage = value;
    OnPropertyChanged("CurrentPage");
    }
    }
    }

    private int _totalPage;

    public int TotalPage
    {
    get
    {
    return _totalPage;
    }

    set
    {
    if(_totalPage != value)
    {
    _totalPage = value;
    OnPropertyChanged("TotalPage");
    }
    }
    }

    private ObservableCollection<FakeDatabase> _fakeSoruce;

    public ObservableCollection<FakeDatabase> FakeSource
    {
    get
    {
    return _fakeSoruce;
    }
    set
    {
    if(_fakeSoruce != value)
    {
    _fakeSoruce = value;
    OnPropertyChanged("FakeSource");
    }
    }
    }

    private List<FakeDatabase> _source;

    public MainViewModel()
    {
    _currentPage = 1;

    _pageSize = 20;

    FakeDatabase fake = new FakeDatabase();

    _source = fake.GenerateFakeSource();

    _totalPage = _source.Count / _pageSize;

    _fakeSoruce = new ObservableCollection<FakeDatabase>();

    List<FakeDatabase> result = _source.Take(20).ToList();

    _fakeSoruce.Clear();

    _fakeSoruce.AddRange(result);

    _firstPageCommand = new DelegateCommand(FirstPageAction);

    _previousPageCommand = new DelegateCommand(PreviousPageAction);

    _nextPageCommand = new DelegateCommand(NextPageAction);

    _lastPageCommand = new DelegateCommand(LastPageAction);
    }

    private void FirstPageAction()
    {
    CurrentPage = 1;

    var result = _source.Take(_pageSize).ToList();

    _fakeSoruce.Clear();

    _fakeSoruce.AddRange(result);
    }

    private void PreviousPageAction()
    {
    if(CurrentPage == 1)
    {
    return;
    }

    List<FakeDatabase> result = new List<FakeDatabase>();

    if(CurrentPage == 2)
    {
    result = _source.Take(_pageSize).ToList();
    }
    else
    {
    result = _source.Skip((CurrentPage - 2) * _pageSize).Take(_pageSize).ToList();
    }

    _fakeSoruce.Clear();

    _fakeSoruce.AddRange(result);

    CurrentPage--;
    }

    private void NextPageAction()
    {
    if(CurrentPage == _totalPage)
    {
    return;
    }

    List<FakeDatabase> result = new List<FakeDatabase>();

    result = _source.Skip(CurrentPage * _pageSize).Take(_pageSize).ToList();

    _fakeSoruce.Clear();

    _fakeSoruce.AddRange(result);

    CurrentPage++;
    }

    private void LastPageAction()
    {
    CurrentPage = TotalPage;

    int skipCount = (_totalPage - 1) * _pageSize;
    int takeCount = _source.Count - skipCount;

    var result = _source.Skip(skipCount).Take(takeCount).ToList();

    _fakeSoruce.Clear();

    _fakeSoruce.AddRange(result);
    }
    }

    复制代码
    public class MainViewModel : ViewModel
        {
            private ICommand _firstPageCommand;
    
            public ICommand FirstPageCommand
            {
                get
                {
                    return _firstPageCommand;
                }
    
                set
                {
                    _firstPageCommand = value;
                }
            }
    
            private ICommand _previousPageCommand;
    
            public ICommand PreviousPageCommand
            {
                get
                {
                    return _previousPageCommand;
                }
    
                set
                {
                    _previousPageCommand = value;
                }
            }
    
            private ICommand _nextPageCommand;
    
            public ICommand NextPageCommand
            {
                get
                {
                    return _nextPageCommand;
                }
    
                set
                {
                    _nextPageCommand = value;
                }
            }
    
            private ICommand _lastPageCommand;
    
            public ICommand LastPageCommand
            {
                get
                {
                    return _lastPageCommand;
                }
    
                set
                {
                    _lastPageCommand = value;
                }
            }
    
            private int _pageSize;
    
            public int PageSize
            {
                get
                {
                    return _pageSize;
                }
                set
                {
                    if(_pageSize != value)
                    {
                        _pageSize = value;
                        OnPropertyChanged("PageSize");
                    }
                }
            }
    
            private int _currentPage;
    
            public int CurrentPage
            {
                get
                {
                    return _currentPage;
                }
    
                set
                {
                    if(_currentPage != value)
                    {
                        _currentPage = value;
                        OnPropertyChanged("CurrentPage");
                    }
                }
            }
    
            private int _totalPage;
    
            public int TotalPage
            {
                get
                {
                    return _totalPage;
                }
    
                set
                {
                    if(_totalPage != value)
                    {
                        _totalPage = value;
                        OnPropertyChanged("TotalPage");
                    }
                }
            }
    
            private ObservableCollection<FakeDatabase> _fakeSoruce;
    
            public ObservableCollection<FakeDatabase> FakeSource
            {
                get
                {
                    return _fakeSoruce;
                }
                set
                {
                    if(_fakeSoruce != value)
                    {
                        _fakeSoruce = value;
                        OnPropertyChanged("FakeSource");
                    }
                }
            }
    
            private List<FakeDatabase> _source;
    
            public MainViewModel()
            {
                _currentPage = 1;
    
                _pageSize = 20;
    
                FakeDatabase fake = new FakeDatabase();
    
                _source = fake.GenerateFakeSource();
    
                _totalPage = _source.Count / _pageSize;
    
                _fakeSoruce = new ObservableCollection<FakeDatabase>();
    
                List<FakeDatabase> result = _source.Take(20).ToList();
    
                _fakeSoruce.Clear();
    
                _fakeSoruce.AddRange(result);
    
                _firstPageCommand = new DelegateCommand(FirstPageAction);
    
                _previousPageCommand = new DelegateCommand(PreviousPageAction);
    
                _nextPageCommand = new DelegateCommand(NextPageAction);
    
                _lastPageCommand = new DelegateCommand(LastPageAction);
            }
    
            private void FirstPageAction()
            {
                CurrentPage = 1;
    
                var result = _source.Take(_pageSize).ToList();
    
                _fakeSoruce.Clear();
    
                _fakeSoruce.AddRange(result);
            }
    
            private void PreviousPageAction()
            {
                if(CurrentPage == 1)
                {
                    return;
                }
    
                List<FakeDatabase> result = new List<FakeDatabase>();
    
                if(CurrentPage == 2)
                {
                    result = _source.Take(_pageSize).ToList();
                }
                else
                {
                    result = _source.Skip((CurrentPage - 2) * _pageSize).Take(_pageSize).ToList();
                }
    
                _fakeSoruce.Clear();
    
                _fakeSoruce.AddRange(result);
    
                CurrentPage--;
            }
    
            private void NextPageAction()
            {
                if(CurrentPage == _totalPage)
                {
                    return;
                }
    
                List<FakeDatabase> result = new List<FakeDatabase>();
    
                result = _source.Skip(CurrentPage * _pageSize).Take(_pageSize).ToList();
    
                _fakeSoruce.Clear();
    
                _fakeSoruce.AddRange(result);
    
                CurrentPage++;
            }
    
            private void LastPageAction()
            {
                CurrentPage = TotalPage;
    
                int skipCount = (_totalPage - 1) * _pageSize;
                int takeCount = _source.Count - skipCount;
    
                var result = _source.Skip(skipCount).Take(takeCount).ToList();
    
                _fakeSoruce.Clear();
    
                _fakeSoruce.AddRange(result);
            }
        }
    复制代码

    绑定到UI的数据源只是需要显示的数据,不会把所有数据都取出来。当选择显示页数时,只需要将新的数据源附上即可。

    总结:如果需要对该分页控件进行扩展,例如,增加每页显示条数功能,只需要在Pager控件中增加相应的依赖属性即可。

    感谢您的阅读,代码点击这里下载。

  • 相关阅读:
    102/107. Binary Tree Level Order Traversal/II
    110. Balanced Binary Tree
    SQL SERVER select,update,delete使用表别名
    C# 有哪些集合
    C# 流总结
    How ASP.NET MVC Works ? (Artech)
    c#扩展方法
    使用缓存的九大误区
    9中浏览器端缓存
    理解AppDomain和AppPool
  • 原文地址:https://www.cnblogs.com/LiZhongZhongY/p/11067667.html
Copyright © 2020-2023  润新知