XAML 如何使用CommunityToolkit中的IncrementalLoadingCollection在WinUI3中实现增量加载

jdgnovmf  于 2023-04-03  发布在  其他
关注(0)|答案(1)|浏览(125)

我一直在一个基于C# WinUI 3的项目上工作,我在我的应用程序中有一个ListView,它使用MySQL从数据库加载数据列表。由于有更多的thank 10k数据,我必须在我的应用程序中实现增量加载。我尝试从WinUI3 : Add contents during runtime to ListView during scroll实现代码,当我打开应用程序时,它最初只加载给予数量的数据,但是当我导航到另一个页面并返回时,页面加载了整个数据(10k)。以下是相关问题的视频:Demo Video
这是我使用的代码:
Course.cs

using System;

namespace Fees_DBASC.Models.DataModels
{
    public class Course
    {
        public Course() { }

        public Course(int id, string name, int semesters, DateTime timestamp)
        {
            Id = id;
            Name = name;
            Semesters = semesters;
            Timestamp = timestamp;
        }

        public int Id
        {
            get;
            set;
        }

        public string Name
        {
            get;
            set;
        }

        public int Semesters
        {
            get;
            set;
        }

        public DateTime Timestamp
        {
            get;
            set;
        }
    }
}

CourseIncrementalSource.cs

using CommunityToolkit.Common.Collections;
using Fees_DBASC.Core.Database;
using Fees_DBASC.Models.DataModels;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace Fees_DBASC.Data.Sources
{
    public class CourseIncrementalSource : IIncrementalSource<Course>
    {
        public CourseIncrementalSource() { }

        public async Task<IEnumerable<Course>> GetPagedItemsAsync(int pageIndex, int pageSize, CancellationToken cancellationToken = default)
        {
            List<Course> items = new List<Course>();

            // Establish a connection to the MySQL database
            string connectionString = GlobalDatabaseConfiguration.Url;
            using (MySqlConnection connection = new MySqlConnection(connectionString))
            {
                await connection.OpenAsync();

                // Create a MySQL command to retrieve the items
                MySqlCommand command = connection.CreateCommand();
                command.CommandText = "SELECT * FROM courses ORDER BY id LIMIT @startIndex, @pageSize";
                command.Parameters.AddWithValue("@startIndex", pageIndex * pageSize);
                command.Parameters.AddWithValue("@pageSize", pageSize);

                // Execute the command and retrieve the data
                using (MySqlDataReader reader = (MySqlDataReader)await command.ExecuteReaderAsync())
                {
                    while (await reader.ReadAsync())
                    {
                        // Map the data to a MyDataItem object
                        Course item = new Course();
                        item.Id = reader.GetInt32(0);
                        item.Name = reader.GetString("name");

                        items.Add(item);
                    }
                }
            }
            return items;
        }
    }
}

Courses.cs(WinUi3页面)

using CommunityToolkit.WinUI;
using Fees_DBASC.Data.Sources;
using Fees_DBASC.Models.DataModels;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;

namespace Fees_DBASC.Views.Pages
{
    public sealed partial class Courses : Page
    {

        public Courses()
        {
            this.InitializeComponent();
            this.Loaded += Courses_Loaded;
        }

        private void Courses_Loaded(object sender, RoutedEventArgs e)
        {
            var collection = new IncrementalLoadingCollection<CourseIncrementalSource, Course>(25, null, null, null);
            CourseList.ItemsSource = collection;
        }

        private void OpenContextMenu(object sender, RightTappedRoutedEventArgs e)
        {
            ListView listView = (ListView)sender;
            bool singleItemSelected = (listView.SelectedItems.Count == 1);
            Delete.IsEnabled = (listView.SelectedItems.Count > 0);
            Edit.IsEnabled = singleItemSelected;

            ContextMenu.ShowAt(listView, e.GetPosition(listView));
            //var a = ((FrameworkElement)e.OriginalSource).DataContext;

        }
    }
}

任何想法如何解决这个问题,我已经通过几个网站,但没有找到答案。

2uluyalo

2uluyalo1#

最后通过在函数中添加await Task.Delay(1, cancellationToken);修复了这个问题。我不确定是什么导致了这个问题,但是添加了一个像1ms这样的小延迟解决了这个问题。
新代码如下所示:

public async Task<IEnumerable<Course>> GetPagedItemsAsync(int pageIndex, int pageSize, CancellationToken cancellationToken = default)
{
    using MySqlConnection connection = new(GlobalDatabaseConfiguration.Url);
    await connection.OpenAsync(cancellationToken);
    MySqlCommand command = connection.CreateCommand();
    command.CommandText = "SELECT * FROM courses ORDER BY id LIMIT @startIndex, @pageSize";
    command.Parameters.AddWithValue("@startIndex", pageIndex * pageSize);
    command.Parameters.AddWithValue("@pageSize", pageSize);
    using MySqlDataReader reader = (MySqlDataReader)await command.ExecuteReaderAsync(cancellationToken);
    while (await reader.ReadAsync(cancellationToken))
    {
        Course course = new()
        {
            Id = reader.GetInt32("id"),
            Name = reader.GetString("name"),
            Semesters = reader.GetInt32("semesters"),
            Timestamp = DateTime.Parse(reader.GetString("timestamp"))
        };
        courseList.Add(course);
    }

    //This line fixed it.
    await Task.Delay(1, cancellationToken);
    return (from course in courseList select course).Skip(pageIndex * pageSize).Take(pageSize);
}

相关问题