您当前的位置: 首页 > 

寒冰屋

暂无认证

  • 0浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

使用动态数据进行数据分页

寒冰屋 发布时间:2020-12-01 19:43:29 ,浏览量:0

目录

介绍

动态数据

数据分页

填充数据源

页面切换

结论

  • 下载资料库

 

介绍

如果您有一个大的数据集合,那么用集合中的所有数据填充项目控件就变得不切实际,更不用说用户不友好了。最好的方法是对数据进行分段,因此项目控件仅显示数据的子集,并允许用户在数据段之间循环。可以使用动态数据库在.NET应用程序中实现这种分页功能,本文将介绍如何在WPF-MVVM应用程序中实现此功能。

动态数据

动态Data是一个可移植的类库,提供包含反应性扩展(Rx)功能的集合。动态数据集合可以是SourceList类型的可观察列表,也可以是SourceCache类型的可观察缓存。这些集合使用可观察到的变更集进行管理,这些变更集是通过调用集合的Connect()运算符创建的,并且可以是类型IObservable或IObservable。数据处理操作(如排序、分组、过滤、数据虚拟化和分页)是使用可链接在一起以执行复杂操作的运算符完成的。截至撰写本文时,该库有60个集合运算符。

要使用动态数据,您的项目必须引用动态数据NuGet包。

数据分页

如上一节所述,动态数据提供两种类型的反应性集合,它们充当数据源。要对数据进行分页,您需要利用SourceCache集合。在示例项目中,此类集合在IEmployeesService实现中定义,并将包含Employee类型的对象。

using Bogus;
using DynamicData;
using PagedData.WPF.Models;
using System;

namespace PagedData.WPF.Services
{
    public class EmployeesService : IEmployeesService
    {
        private readonly ISourceCache _employees;

        public EmployeesService() => _employees = new SourceCache(e => e.ID);

        public IObservable
               EmployeesConnection() => _employees.Connect();

        public void LoadData()
        {
            var employeesFaker = new Faker()
                .RuleFor(e => e.ID, f => f.IndexFaker)
                .RuleFor(e => e.FirstName, f => f.Person.FirstName)
                .RuleFor(e => e.LastName, f => f.Person.LastName)
                .RuleFor(e => e.Age, f => f.Random.Int(20, 60))
                .RuleFor(e => e.Gender, f => f.Person.Gender.ToString());

            _employees.AddOrUpdate(employeesFaker.Generate(1500));
        }
    }
}

在LoadData()中,通过调用集合的AddOrUpdate()方法将数据添加到可观察的缓存中。该方法有两个重载:一个重载单个对象,另一个重载对象集合。使用Bogus将1500个employee对象添加到可观察的集合中,该集合会生成20到60岁之间的employee的伪数据。

集合的可观察更改集由EmployeesConnection()公开,调用集合的Connect()运算符。然后,可以将可观察到的变更集绑定到视图模型中的ReadOnlyObservableCollection,并且还可以调用其他运算符来执行数据管理操作。

public class MainWindowViewModel : ViewModelBase
{
    private const int PAGE_SIZE = 25;
    private const int FIRST_PAGE = 1;

    private readonly IEmployeesService _employeesService;
    private readonly ISubject _pager;

    private readonly ReadOnlyObservableCollection _employees;
    public ReadOnlyObservableCollection Employees => _employees;

    public MainWindowViewModel(IEmployeesService employeesService)
    {
        _employeesService = employeesService;

        _pager = new BehaviorSubject(new PageRequest(FIRST_PAGE, PAGE_SIZE));

        _employeesService.EmployeesConnection()
            .Sort(SortExpressionComparer.Ascending(e => e.ID))
            .Page(_pager)
            .Do(change => PagingUpdate(change.Response))
            .ObserveOnDispatcher()
            .Bind(out _employees)
            .Subscribe();
    }

    ...
}

要对数据进行分页,首先必须对其进行排序。然后,您可以调用Page()运算符,该运算符采用ISubject来指定第一页以及每页中的项目数。当集合发生变化时,Do()操作符提供更新,因此我使用它来使用IPagedChangeSet响应更新几个视图模型属性。

private void PagingUpdate(IPageResponse response)
{
    TotalItems = response.TotalSize;
    CurrentPage = response.Page;
    TotalPages = response.Pages;
}
填充数据源

当应用程序加载时,数据将被添加到反应性集合中。这是通过视图模型中的LoadDataCommand完成的。

private RelayCommand _loadDataCommand;
public RelayCommand LoadDataCommand =>
    _loadDataCommand ??= new RelayCommand(_ => LoadEmployeeData());

private void LoadEmployeeData() => _employeesService.LoadData();
页面切换

数据页面之间的循环是使用先前定义的ISubject来完成的,该对象具有一个传递了PageRequest对象的OnNext()运算符。

...

#region Previous page command
private RelayCommand _previousPageCommand;
public RelayCommand PreviousPageCommand => _previousPageCommand ??=
    new RelayCommand(_ => MoveToPreviousPage(), _ => CanMoveToPreviousPage());

private void MoveToPreviousPage() =>
    _pager.OnNext(new PageRequest(_currentPage - 1, PAGE_SIZE));

private bool CanMoveToPreviousPage() => CurrentPage > FIRST_PAGE;
#endregion

#region Next page command
private RelayCommand _nextPageCommand;
public RelayCommand NextPageCommand => _nextPageCommand ??=
    new RelayCommand(_ => MoveToNextPage(), _ => CanMoveToNextPage());

private void MoveToNextPage() =>
    _pager.OnNext(new PageRequest(_currentPage + 1, PAGE_SIZE));

private bool CanMoveToNextPage() => CurrentPage < TotalPages;
#endregion

#region First page command
private RelayCommand _firstPageCommand;
public RelayCommand FirstPageCommand => _firstPageCommand ??=
    new RelayCommand(_ => MoveToFirstPage(), _ => CanMoveToFirstPage());

private void MoveToFirstPage() =>
    _pager.OnNext(new PageRequest(FIRST_PAGE, PAGE_SIZE));

private bool CanMoveToFirstPage() => CurrentPage > FIRST_PAGE;
#endregion

#region Last page command
private RelayCommand _lastPageCommand;
public RelayCommand LastPageCommand => _lastPageCommand ??=
    new RelayCommand(_ => MoveToLastPage(), _ => CanMoveToLastPage());

private void MoveToLastPage() =>
    _pager.OnNext(new PageRequest(_totalPages, PAGE_SIZE));

private bool CanMoveToLastPage() => CurrentPage < TotalPages;
#endregion

这就是分页逻辑所需要的。然后可以将视图模型的属性和命令绑定到视图中的必要元素上。


  
      
          
      
  

  
      
          
          
      

      
          
              
              
              
              
              
          
      

      
          
              
          
          
              
          
          
              
                  
                      
                      
                  
              
          
          
              
          
          
              
          
      

      
  
结论

希望您从本文中学到了有用的东西。如前所述,Dynamic Data具有大量的集合运算符,因此请看一下它们还可以做什么。您也可以从文章顶部的链接下载本文的示例项目。

关注
打赏
1665926880
查看更多评论
立即登录/注册

微信扫码登录

0.1258s