赞
踩
我们这次详细了解一下列表通知的底层是怎么实现的
我为了方便展示源代码,我将代码提交到了代码仓库里面
想要看的话看我前面的文章就可以了
和我之前的代码差不多,详细的就看我的源码好了,我会用TabItem来简单说明的。这就是初始配置的代码了
<UserControl x:Class="DataGrid_Pagination.Views.Demo1View" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:DataGrid_Pagination.Views" mc:Ignorable="d" xmlns:hc="https://handyorg.github.io/handycontrol" xmlns:viewModels="clr-namespace:DataGrid_Pagination.ViewModels" d:DesignHeight="450" d:DesignWidth="800"> <UserControl.DataContext> <viewModels:Demo1ViewModel x:Name="ViewModel"/> </UserControl.DataContext> <DockPanel> <hc:Pagination MaxPageCount="10" DockPanel.Dock="Bottom" Margin="4 7" PageIndex="5" IsJumpEnabled="True" /> <DataGrid ItemsSource="{Binding CollectionData.Data}"> </DataGrid> </DockPanel> </UserControl>
namespace DataGrid_Pagination.ViewModels { public partial class Demo1ViewModel : ObservableObject { public Demo1View Demo1View { get; set; } [ObservableProperty] private CollectionData<Student> collectionData = new CollectionData<Student>(); public Demo1ViewModel() { CollectionData = new CollectionData<Student>() { Data = new Student().FakeMany(10) }; CollectionData.Init(); CollectionData.CollectionView.Refresh(); } } }
<UserControl x:Class="DataGrid_Pagination.Views.Demo2View" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:DataGrid_Pagination.Views" mc:Ignorable="d" xmlns:hc="https://handyorg.github.io/handycontrol" xmlns:viewModels="clr-namespace:DataGrid_Pagination.ViewModels" d:DesignHeight="450" d:DesignWidth="800"> <UserControl.DataContext> <viewModels:Demo2ViewModel x:Name="ViewModel"/> </UserControl.DataContext> <DockPanel> <hc:Pagination MaxPageCount="{Binding PageCount}" DockPanel.Dock="Bottom" Margin="4 7" PageIndex="{Binding PageIndex,Mode=TwoWay}" IsJumpEnabled="True" /> <DataGrid ItemsSource="{Binding CollectionData.Data}"> </DataGrid> </DockPanel> </UserControl>
namespace DataGrid_Pagination.ViewModels { public partial class Demo2ViewModel : ObservableObject { public Demo2View View { get; set; } [ObservableProperty] private CollectionData<Student> collectionData = new CollectionData<Student>(); private int pageIndex = 1; public int PageIndex { get => pageIndex; set { SetProperty(ref pageIndex, value); CollectionData.CollectionView.Refresh(); } } public readonly int PageSize = 10; [ObservableProperty] private int pageCount = 1; public Demo2ViewModel() { CollectionData = new CollectionData<Student>() { Data = new Student().FakeMany(150) }; CollectionData.Binding(); CollectionData.CollectionView.CollectionChanged += (s, e) => { var count = CollectionData.Data.ToList().Count; PageCount = (int)Math.Ceiling((decimal)(count / PageSize)); }; CollectionData.CollectionView.Filter = (item) => { if (!(item is Student)) { throw new Exception("属性类型不为Student"); } var index = CollectionData.Data.ToList().IndexOf((Student)item); return PageIndex == index / PageSize + 1; }; CollectionData.CollectionView.Refresh(); } } }
小数据量没问题,但是大数据会出问题。因为主要的计算是indexOf和每个项的Filter。o(n)*o(n)=o(n^2),复杂度太高了。
Linq过滤就是我们每次都更新CollectionView绑定的对象,触发更新
public partial class CollectionData<T>:ObservableObject where T : class { [ObservableProperty] private IEnumerable<T> data = new List<T>(); public ICollectionView CollectionView { get; set; } public CollectionData() { } public void Binding() { CollectionView = CollectionViewSource.GetDefaultView(Data); } }
<UserControl x:Class="DataGrid_Pagination.Views.Demo3View" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:DataGrid_Pagination.Views" mc:Ignorable="d" xmlns:hc="https://handyorg.github.io/handycontrol" xmlns:viewModels="clr-namespace:DataGrid_Pagination.ViewModels" d:DesignHeight="450" d:DesignWidth="800"> <UserControl.DataContext> <viewModels:Demo3ViewModel x:Name="ViewModel" /> </UserControl.DataContext> <DockPanel> <hc:Pagination MaxPageCount="{Binding PageCount}" DockPanel.Dock="Bottom" Margin="4 7" PageIndex="{Binding PageIndex,Mode=TwoWay}" IsJumpEnabled="True" /> <DataGrid ItemsSource="{Binding CollectionData.Data}"> </DataGrid> </DockPanel> </UserControl>
namespace DataGrid_Pagination.ViewModels { public partial class Demo3ViewModel : ObservableObject { public Demo3View View { get; set; } [ObservableProperty] private CollectionData<Student> collectionData = new CollectionData<Student>(); private int pageIndex = 1; public int PageIndex { get => pageIndex; set { SetProperty(ref pageIndex, value); CollectionData.CollectionView.Refresh(); } } public readonly int PageSize = 10; [ObservableProperty] private int pageCount = 1; public readonly List<Student> Students = new Student().FakeMany(150).ToList(); public Demo3ViewModel() { CollectionData = new CollectionData<Student>() { Data = Students.Take(PageSize), }; CollectionData.Binding(); CollectionData.CollectionView.CollectionChanged += (s, e) => { var count = Students.Count; PageCount = (int)Math.Ceiling((decimal)(count / PageSize)); CollectionData.Data = Students.Skip((PageIndex - 1) * PageSize).Take(PageSize); }; } } }
分页是我们最常用的功能,这次简单实现了分页的效果。HandyControl没有提供主动的分页,需要我们组合一下。详细代码可以看我的Github仓库。三种过滤我都写了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。