背水一战 Windows 10 (57) - 控件(集合类): ListViewBase - 增量加载, 分步绘制
2021-05-12 19:27
标签:scrolling pac namespace open eal tor lis 允许 pat [源码下载] 作者:webabcd 示例 Controls/CollectionControl/ListViewBaseDemo/ListViewBaseDemo3.xaml Controls/CollectionControl/ListViewBaseDemo/ListViewBaseDemo3.xaml.cs Controls/CollectionControl/ListViewBaseDemo/ListViewBaseDemo4.xaml.cs OK 背水一战 Windows 10 (57) - 控件(集合类): ListViewBase - 增量加载, 分步绘制 标签:scrolling pac namespace open eal tor lis 允许 pat 原文地址:http://www.cnblogs.com/lonelyxmas/p/7568325.html
介绍
背水一战 Windows 10 之 控件(集合类 - ListViewBase)
1、ListViewBase 的增量加载
Controls/CollectionControl/ListViewBaseDemo/MyIncrementalLoading.cs/*
* 演示如何实现 ISupportIncrementalLoading 接口,以便为 ListViewBase 的增量加载提供数据
*
*
* ISupportIncrementalLoading - 用于支持增量加载
* HasMoreItems - 是否还有更多的数据
* IAsyncOperation
Page
x:Class="Windows10.Controls.CollectionControl.ListViewBaseDemo.ListViewBaseDemo3"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Windows10.Controls.CollectionControl.ListViewBaseDemo"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
Grid Background="Transparent" Margin="10 0 10 10">
TextBlock Name="lblMsg" />
ListView x:Name="listView" Width="300" Height="300" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0 30 0 0">
ListView.ItemTemplate>
DataTemplate>
Border Background="Blue" Width="200" CornerRadius="3" HorizontalAlignment="Left">
TextBlock Text="{Binding Name}" />
Border>
DataTemplate>
ListView.ItemTemplate>
ListView>
TextBlock Name="lblLog" Margin="0 350 0 0" />
Grid>
Page>
/*
* ListViewBase(基类) - 列表控件基类(继承自 Selector, 请参见 /Controls/SelectionControl/SelectorDemo.xaml)
* IncrementalLoadingTrigger - 增量加载的触发器
* Edge - 允许触发增量加载,默认值
* None - 禁止触发增量加载
* DataFetchSize - 预提数据的大小,默认值 3.0
* 本例将此值设置为 4.0 ,其效果为(注:本例中的 ListView 每页可显示的数据量为 6 条或 7 条,以下计算需基于此)
* 1、先获取 1 条数据,为的是尽量快地显示数据
* 2、再获取 4.0 * 1 条数据
* 3、再获取 4.0 * (6 或 7,如果 ListView 当前显示了 6 条数据则为 6,如果 ListView 当前显示了 7 条数据则为 7) 条数据
* 4、以后每次到达阈值后,均增量加载 4.0 * (6 或 7,如果 ListView 当前显示了 6 条数据则为 6,如果 ListView 当前显示了 7 条数据则为 7) 条数据
* IncrementalLoadingThreshold - 增量加载的阈值,默认值 0.0
* 本例将此值设置为 2.0 ,其效果为(注:本例中的 ListView 每页可显示的数据量为 6 条或 7 条)
* 1、滚动中,如果已准备好的数据少于 2.0 * (6 或 7,如果 ListView 当前显示了 6 条数据则为 6,如果 ListView 当前显示了 7 条数据则为 7) 条数据,则开始增量加载
*
*
* 本例用于演示如何实现 ListViewBase 的增量加载(数据源需要实现 ISupportIncrementalLoading 接口,详见:MyIncrementalLoading.cs)
*/
using Windows.UI.Xaml.Controls;
using System.Linq;
using System.Collections.Specialized;
using System;
using Windows10.Common;
using Windows.UI.Xaml;
namespace Windows10.Controls.CollectionControl.ListViewBaseDemo
{
public sealed partial class ListViewBaseDemo3 : Page
{
// 实现了增量加载的数据源
private MyIncrementalLoading
2、ListViewBase 的分步绘制
Controls/CollectionControl/ListViewBaseDemo/ListViewBaseDemo4.xamlPage
x:Class="Windows10.Controls.CollectionControl.ListViewBaseDemo.ListViewBaseDemo4"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Windows10.Controls.CollectionControl.ListViewBaseDemo"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
Grid Background="Transparent">
GridView x:Name="gridView" Margin="10 0 10 10" ContainerContentChanging="gridView_ContainerContentChanging">
GridView.ItemTemplate>
DataTemplate>
StackPanel Width="80" Height="80" Background="Blue">
Rectangle x:Name="placeholderRectangle" Fill="Red" Height="10" Opacity="0" />
TextBlock x:Name="lblName" Text="{Binding Name}" Foreground="Yellow" />
TextBlock x:Name="lblAge" Text="{Binding Age}" Foreground="Aqua" />
TextBlock x:Name="lblIsMale" Text="{Binding IsMale}" Foreground="Gray" />
StackPanel>
DataTemplate>
GridView.ItemTemplate>
GridView>
Grid>
Page>
/*
* ListViewBase(基类) - 列表控件基类(继承自 Selector, 请参见 /Controls/SelectionControl/SelectorDemo.xaml)
* ContainerContentChanging - 数据虚拟化时,项容器的内容发生变化时触发的事件(仅 ItemsStackPanel 和 ItemsWrapGrid 有效)
*
*
* 当 ListViewBase 的一屏需要显示的数据量极大时(一屏的 item 多,且每个 item 中的 element 也多),由于每次滚动时需要绘制当前屏的每个 element,这需要占用大量的 ui 资源,所以就会有一些卡顿
* 为了解决这个问题 uwp 给出了两种解决方案
* 1、设置 ListViewBase 的 ShowsScrollingPlaceholders 属性为 true(默认值),每次显示 item 时先显示占位符(尚不清楚怎么修改这个占位符的背景色),然后再绘制内容
* 相关演示请参见:/Controls/CollectionControl/ListViewBaseDemo/ListViewBaseDemo1.xaml
* 2、通过 ListViewBase 的 ContainerContentChanging 事件,分步绘制 item 中的 element
* 本例即介绍这种方法。注意在 uwp 中已经不用这么麻烦了,可以通过 x:Bind 和 x:Phase 来实现,请参见:/Bind/PhaseDemo.xaml
*
*
* 本例用于演示如何实现 ListViewBase 的分步绘制(大数据量流畅滚动)
*
*
* 注:
* 虚拟化布局控件用于减少创建的 item 数量
* 分步绘制用于在绘制 item 时,分阶段绘制 item 上的元素
*/
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Shapes;
using Windows10.Common;
namespace Windows10.Controls.CollectionControl.ListViewBaseDemo
{
public sealed partial class ListViewBaseDemo4 : Page
{
public ListViewBaseDemo4()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
gridView.ItemsSource = TestData.GetEmployees(1000);
// 默认值是 true,即为了保证流畅,每次显示 item 时先会显示占位符(application 级的背景色块),然后再绘制内容
// 本例演示 ContainerContentChanging 事件的使用,所以不会用到这个
gridView.ShowsScrollingPlaceholders = false;
}
private void gridView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
// 交由我处理吧(不用系统再处理了)
args.Handled = true;
// 第 1 阶段绘制
// args.Phase.ToString(); // 0
StackPanel templateRoot = (StackPanel)args.ItemContainer.ContentTemplateRoot;
Rectangle placeholderRectangle = (Rectangle)templateRoot.FindName("placeholderRectangle");
TextBlock lblName = (TextBlock)templateRoot.FindName("lblName");
TextBlock lblAge = (TextBlock)templateRoot.FindName("lblAge");
TextBlock lblIsMale = (TextBlock)templateRoot.FindName("lblIsMale");
// 显示自定义占位符(也可以不用这个,而是直接显示 item 的背景)
placeholderRectangle.Opacity = 1;
// 除了占位符外,所有 item 全部暂时不绘制
lblName.Opacity = 0;
lblAge.Opacity = 0;
lblIsMale.Opacity = 0;
// 开始下一阶段的绘制
args.RegisterUpdateCallback(ShowName);
}
private void ShowName(ListViewBase sender, ContainerContentChangingEventArgs args)
{
// 第 2 阶段绘制
// args.Phase.ToString(); // 1
Employee employee = (Employee)args.Item;
SelectorItem itemContainer = (SelectorItem)args.ItemContainer;
StackPanel templateRoot = (StackPanel)itemContainer.ContentTemplateRoot;
TextBlock lblName = (TextBlock)templateRoot.FindName("lblName");
// 绘制第 2 阶段的内容
lblName.Text = employee.Name;
lblName.Opacity = 1;
// 开始下一阶段的绘制
args.RegisterUpdateCallback(ShowAge);
}
private void ShowAge(ListViewBase sender, ContainerContentChangingEventArgs args)
{
// 第 3 阶段绘制
// args.Phase.ToString(); // 2
Employee employee = (Employee)args.Item;
SelectorItem itemContainer = (SelectorItem)args.ItemContainer;
StackPanel templateRoot = (StackPanel)itemContainer.ContentTemplateRoot;
TextBlock lblAge = (TextBlock)templateRoot.FindName("lblAge");
// 绘制第 3 阶段的内容
lblAge.Text = employee.Age.ToString();
lblAge.Opacity = 1;
// 开始下一阶段的绘制
args.RegisterUpdateCallback(ShowIsMale);
}
private void ShowIsMale(ListViewBase sender, ContainerContentChangingEventArgs args)
{
// 第 4 阶段绘制
// args.Phase.ToString(); // 3
Employee employee = (Employee)args.Item;
SelectorItem itemContainer = (SelectorItem)args.ItemContainer;
StackPanel templateRoot = (StackPanel)itemContainer.ContentTemplateRoot;
Rectangle placeholderRectangle = (Rectangle)templateRoot.FindName("placeholderRectangle");
TextBlock lblIsMale = (TextBlock)templateRoot.FindName("lblIsMale");
// 绘制第 4 阶段的内容
lblIsMale.Text = employee.IsMale.ToString();
lblIsMale.Opacity = 1;
// 隐藏自定义占位符
placeholderRectangle.Opacity = 0;
}
}
}
[源码下载]
文章标题:背水一战 Windows 10 (57) - 控件(集合类): ListViewBase - 增量加载, 分步绘制
文章链接:http://soscw.com/index.php/essay/84818.html