首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

Windows 8 Store Apps 開發實戰(54):實現 ISupportIncrementalLoading 實現 ListView 增量加載數據

     編輯:關於.NET

前言

在 Windows 8 Store Apps 開發中,當面對大量數據時,一次性加載所有項目會嚴重影響效能與記憶體使用。透過實作 ISupportIncrementalLoading 介面,我們可以讓 ListViewBase(包含 ListView 與 GridView)支援「增量加載」,隨著使用者滾動動態載入資料,極大提升使用者體驗。

核心概念:ISupportIncrementalLoading 介面

ISupportIncrementalLoading 定義了兩個關鍵成員:

  • HasMoreItems:回傳布林值,指示是否還有更多資料可供加載。
  • LoadMoreItemsAsync(uint count):非同步方法,負責實際載入指定數量的資料,並回傳 LoadMoreItemsResult(包含實際載入筆數 Count)。

通用增量加載集合類:MyIncrementalLoading<T>

以下實作一個泛型集合類,繼承 ObservableCollection<T> 並實作 ISupportIncrementalLoading,可重複用於各類資料源:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Data;

namespace XamlDemo.Binding
{
    public class MyIncrementalLoading<T> : ObservableCollection<T>, ISupportIncrementalLoading
    {
        private bool _isBusy = false;
        private Func<int, int, List<T>> _funcGetData;
        private uint _totalCount = 0;

        public MyIncrementalLoading(uint totalCount, Func<int, int, List<T>> getDataFunc)
        {
            _funcGetData = getDataFunc;
            _totalCount = totalCount;
        }

        public bool HasMoreItems
        {
            get { return this.Count < _totalCount; }
        }

        public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
        {
            if (_isBusy)
                throw new InvalidOperationException("正在加載中,請稍候...");

            _isBusy = true;
            var dispatcher = Window.Current.Dispatcher;

            return AsyncInfo.Run(async (token) =>
            {
                try
                {
                    // 模擬網路/資料庫延遲
                    await Task.Delay(1000);

                    int startIndex = this.Count;
                    List<T> items = null;

                    // 必須在 UI 執行緒加入集合,以觸發介面更新
                    await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                    {
                        items = _funcGetData(startIndex, (int)count);
                        foreach (var item in items)
                            this.Add(item);
                    });

                    return new LoadMoreItemsResult { Count = (uint)items.Count };
                }
                finally
                {
                    _isBusy = false;
                }
            });
        }
    }
}

XAML 介面:設定增量加載觸發參數

在 ListView 上透過三個屬性微調加載行為:

  • IncrementalLoadingTrigger:Edge(預設,滾動到底部觸發)或 None(停用)。
  • DataFetchSize:預先抓取資料的倍數(預設 3.0)。
  • IncrementalLoadingThreshold:觸發閾值倍數(預設 0.0)。
<Page x:Class="XamlDemo.Binding.IncrementalLoading"
      xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:XamlDemo.Binding"
      xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d">
    <Grid Background="Transparent">
        <Grid Margin="120 0 0 10">
            <TextBlock Name="lblMsg" FontSize="14.667" />
            <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}" FontSize="14.667" />
                        </Border>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
            <TextBlock Name="lblLog" FontSize="14.667" Margin="0 350 0 0" />
        </Grid>
    </Grid>
</Page>

後端程式碼:綁定與參數設定

using Windows.UI.Xaml.Controls;
using XamlDemo.Model;
using System.Linq;
using System.Collections.Specialized;
using System;

namespace XamlDemo.Binding
{
    public sealed partial class IncrementalLoading : Page
    {
        private MyIncrementalLoading<Employee> _employees;

        public IncrementalLoading()
        {
            this.InitializeComponent();
            this.Loaded += IncrementalLoading_Loaded;
        }

        void IncrementalLoading_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            // 設定增量加載參數
            listView.IncrementalLoadingTrigger = IncrementalLoadingTrigger.Edge;
            listView.DataFetchSize = 4.0;
            listView.IncrementalLoadingThreshold = 2.0;

            // 建立資料源:總共 1000 筆,分頁載入
            _employees = new MyIncrementalLoading<Employee>(1000, (startIndex, count) =>
            {
                lblLog.Text += string.Format("從索引 {0} 開始獲取 {1} 條資料\n", startIndex, count);
                return TestData.GetEmployees().Skip(startIndex).Take(count).ToList();
            });

            _employees.CollectionChanged += _employees_CollectionChanged;
            listView.ItemsSource = _employees;
        }

        void _employees_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            lblMsg.Text = "已獲取資料筆數:" + _employees.Count;
        }
    }
}

關鍵參數運作解析

假設 ListView 每頁可顯示 6~7 筆資料:

  1. 首次載入 1 筆,儘快呈現畫面。
  2. 再載入 4.0 × 1 = 4 筆。
  3. 之後每次觸發載入 4.0 × (6 或 7) 筆。
  4. 當「已準備好但未顯示的資料」少於 2.0 × (6 或 7) 筆時,啟動下一輪加載。

總結

透過 ISupportIncrementalLoading 與 MyIncrementalLoading<T> 封裝,開發者只需專注於「如何取得分頁資料」,即可輕鬆實現流暢、高效能的無限滾動列表。此模式適用於所有繼承自 ListViewBase 的控制項。

原始碼下載:https://files.cnblogs.com/webabcd/Windows8.rar

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved