我无法在我的 .NET Maui 应用程序中执行逐渐滚动

问题描述 投票:0回答:1

我是 .NET Maui 的新手,我正在创建我的第一个应用程序,该应用程序首先检查 dll 文件的接口实现,然后用户输入一个数字,程序应该输出最多到它的所有素数。问题出现在可视化中,当处理大量数据时,我的应用程序本身会挂起,所以我决定将其设为异步。这没有帮助,因为当可视化尝试列出这些数字时,它本身会挂起。然后我决定添加逐渐滚动,但它不起作用。在调试中这个事件不起作用。 这是 MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:PrimeNumApp"
             x:Class="PrimeNumApp.MainPage">
    
        <VerticalStackLayout
            Padding="30,0"
            Spacing="25">
            <Label
                Text="Cписок простых чисел"
                Style="{StaticResource Headline}"
                SemanticProperties.HeadingLevel="Level1" />
            <Image 
                Source="kitten.gif"
                HeightRequest="200" 
                HorizontalOptions="Center"  
                IsAnimationPlaying="True" />
            <Entry
                x:Name="NumberEntry"
                Placeholder="Введите число" />
            <StackLayout
                Orientation="Horizontal"
                Spacing="5"
                >
                <Button
                    x:Name="LoadBtn"
                    Text="Загрузить сборку" 
                    Clicked="OnLoadClicked"
                    HorizontalOptions="FillAndExpand"
                    BackgroundColor="Gray" />
                <Button
                    x:Name="StartBtn"
                    Text="Посчитать"
                    Clicked="OnStartClicked"
                    IsEnabled="False"
                    HorizontalOptions="FillAndExpand"
                    BackgroundColor="DarkRed" />
            </StackLayout>
            <CollectionView x:Name="PrimeNumCollection"
                            
                            RemainingItemsThreshold="5"
                            RemainingItemsThresholdReached="OnCollectionViewRemainingItemsThresholdReached">
                <CollectionView.ItemsLayout>
                    <LinearItemsLayout Orientation="Vertical" />
                </CollectionView.ItemsLayout>
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <TextCell Text="{Binding}"
                  TextColor="White"/>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
        </VerticalStackLayout>

</ContentPage>

这是 MainPage.xaml.cs

using Contract;
using Microsoft.Maui.Controls;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Reflection;
using System.Text;

namespace PrimeNumApp
{
    public partial class MainPage : ContentPage, INotifyPropertyChanged
    {
        private bool _isImplemented;
        private Assembly _assembly;
        private string _realizationPath;
        private IPrimeGenerator _primeNumberGenerator;
        private const int PageSize = 5;
        private int _currentPage = 0;
        public ObservableCollection<int> DisplayablePrimeNums { get; set; }
        private List<int> _allPrimeNumbers = new List<int>();
        public MainPage()
        {
            InitializeComponent();
            DisplayablePrimeNums = new ObservableCollection<int>();
            PrimeNumCollection.ItemsSource = DisplayablePrimeNums;
            PrimeNumCollection.RemainingItemsThresholdReached += OnCollectionViewRemainingItemsThresholdReached;
            

        }
        public async void OnStartClicked(object sender, EventArgs e)
        {
            if (int.TryParse(NumberEntry.Text, out int number))
            {
                try
                {
                    _allPrimeNumbers = await Task.Run(() => _primeNumberGenerator!.GetPrimeNumbers(number));
                    DisplayablePrimeNums.Clear();
                    LoadNextPage();
                    
                }
                catch (Exception ex)
                {
                    await DisplayAlert("Ошибка", ex.Message, "OK");
                }
            }
            else
            {
                await DisplayAlert("Ошибка", "Вы ввели не натуральное число", "OK");
            }
                        
        }
        private void LoadNextPage()
        {
            foreach (int number in _allPrimeNumbers.GetRange(_currentPage, PageSize))
            {
                DisplayablePrimeNums.Add(number);
            }

            _currentPage += PageSize;
        }
        public void OnCollectionViewRemainingItemsThresholdReached(object sender, EventArgs e)
        {
            LoadNextPage();
        }
        public async void OnLoadClicked(object sender, EventArgs e)
        {
            await PickDll();
        }
        private async Task PickDll()
        {
            var customFileType = new FilePickerFileType(
                    new Dictionary<DevicePlatform, IEnumerable<string>>
                    {
                    { DevicePlatform.WinUI, new[] { ".dll" } },
                    });

            try
            {
                var result = await FilePicker.PickAsync(new PickOptions()
                {
                    FileTypes = customFileType,
                    PickerTitle = "Выберите файл формата .dll"
                });

                if (result != null)
                {
                    _realizationPath = result.FullPath;
                    await LoadDll();
                }
            }
            catch (Exception ex)
            {
                await DisplayAlert("Ошибка", "Ошибка при загрузке сборки: " + ex.Message, "OK");
            }
        }
        private async Task LoadDll()
        {
            _assembly = Assembly.LoadFrom(_realizationPath);
            await CheckContractRealization();
        }
        private async Task CheckContractRealization()
        {
            _isImplemented = _assembly.GetTypes().Any(type => type.GetInterfaces().Contains(typeof(IPrimeGenerator)));
            if (_isImplemented)
            {
                LoadBtn.BackgroundColor = Colors.Green;
                StartBtn.IsEnabled = true;
                StartBtn.BackgroundColor = Colors.Gray;
                var primeGeneratorType = _assembly.GetTypes()
                        .Where(type => typeof(IPrimeGenerator).IsAssignableFrom(type) && type.IsClass)
                        .Select(type => type)
                        .First();

                _primeNumberGenerator = (IPrimeGenerator)Activator.CreateInstance(primeGeneratorType)!;
            }
            else
            {
                await DisplayAlert("Ошибка", "Реализация не соответсвует контракту", "OK");
            }
        }

    }

}

我尝试更改和删除滚动条本身,在 CollectionView 中显示 DataTemplate,但它不起作用

c# .net maui
1个回答
0
投票

提供的源代码存在多个问题:

  1. 您正在一次加载所有素数。因此,如果您添加一个巨大的数字,它将尝试立即获取素数,这对于性能来说并不是最好的。增量加载意味着从更大的块中加载一些数据,然后当到达该数据的末尾时加载更多数据。所以你应该改进你的 GetPrimeNumbers 来限制它,然后当你达到限制时再获取更多。
  2. MAUI 提供了使用
    OnCollectionViewRemainingItemsThresholdReached
    检测您是否即将到达列表末尾的功能,然后获取更多数据。几乎没有什么问题需要你解决。您已经在 xaml 中声明了该事件,但也在构造函数中进行了声明。所以只做一次。然后,例如,如果您获得前 20 个素数,那么当您到达最后 5 个素数时,将调用方法
    OnCollectionViewRemainingItemsThresholdReached
    ,您可以在其中加载 20 个以上素数。
  3. 另一个问题是代码的组织而不是绑定到属性。遵循 MVVM 模式绑定到正确的属性。
© www.soinside.com 2019 - 2024. All rights reserved.