Don't put your collectionview inside a scrollview. This remove virtualization by render the whole list items.
Performance Issue with CollectionView in .NET MAUI
Hello,
I am experiencing slow performance issues with .NET MAUI's CollectionView on Android. I am using .NET 7 with VS 17.6.5
I suspect the issue may be related to the use of controls within CollectionView.ItemTemplate. Please help me find a solution to this problem.
using CommunityToolkit.Mvvm.ComponentModel;
using PaySub.Utlis;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows.Input;
using static PaySub.Models.SubscriptionData;
namespace PaySub.ViewModels
{
public partial class ShoppingCartYViewModels : ObservableObject
{
[ObservableProperty]
ObservableCollection<Plan> planY;
public ShoppingCartYViewModels()
{
LoadDataY();
}
private async void LoadDataY()
{
string filePath = "sabafon_data.json";
var carriers = await FileAssetHelper.ReadJsonFileAsync(filePath);
PlanY = new ObservableCollection<Plan>(carriers["sabafon"].card.ToList());
}
}
}
<?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"
x:Class="PaySub.Views.ShoppingCartYPage"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:viewmodel="clr-namespace:PaySub.ViewModels"
xmlns:c="clr-namespace:PaySub.Controls"
Title="{StaticResource BtnPayPlan_title}"
BackgroundColor="{StaticResource Tertiary}"
>
<ContentPage.BindingContext>
<viewmodel:ShoppingCartYViewModels/>
</ContentPage.BindingContext>
<ScrollView Padding="10"
VerticalScrollBarVisibility="Always"
VerticalOptions="FillAndExpand">
<CollectionView ItemsSource="{Binding PlanY }" BackgroundColor="White" x:Name="CVProductList"
VerticalOptions="StartAndExpand"
SelectionMode="Single"
>
<CollectionView.ItemTemplate>
<DataTemplate>
<!--<c:CardView Title="{Binding name}"
Price="{Binding price}"
Description="{Binding description}"
CallDuration="{Binding call_duration}"
Messages="{Binding messages}"
InternetSize="{Binding internet_size}"
DaysDuration="{Binding days_duration}"/>-->
<Frame BackgroundColor="#f2f2f2" BorderColor="#e6e6e6"
CornerRadius="10" HasShadow="True"
Padding="10" Margin="5">
<Frame.Background>
<LinearGradientBrush EndPoint="0,1">
<GradientStop Color="#cb2243"
Offset="0.1" />
<GradientStop Color="#d80042"
Offset="1.0" />
</LinearGradientBrush>
</Frame.Background>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.ColumnSpan="2" Text="{Binding name}" TextColor="White" HorizontalOptions="Center" />
<StackLayout Grid.Row="1" Orientation="Vertical">
<Image HorizontalOptions="Start" />
<Label Text="{Binding price}" TextColor="White" HorizontalOptions="Start" />
<Image HorizontalOptions="Start" />
<Label Text="{Binding description}" TextColor="White" HorizontalOptions="Start" />
<Image Source="clock.png" HeightRequest="20" WidthRequest="20" HorizontalOptions="Start" >
</Image>
<Label Text="{Binding days_duration}" TextColor="White" HorizontalOptions="Start" />
</StackLayout>
<StackLayout Grid.Row="1" Grid.Column="1" Orientation="Vertical">
<Image Source="message.png" HeightRequest="20" WidthRequest="20" HorizontalOptions="End" >
</Image>
<Label Text="{Binding messages}" TextColor="White" HorizontalOptions="End" />
<Image Source="phone_call.png" HeightRequest="20" WidthRequest="20" HorizontalOptions="End" >
</Image>
<Label Text="{Binding call_duration}" TextColor="White" HorizontalOptions="End" />
<Image Source="internet.png" HeightRequest="20" WidthRequest="20" HorizontalOptions="End" >
</Image>
<Label Text="{Binding internet_size}" TextColor="White" HorizontalOptions="End" />
</StackLayout>
<Button x:Name="butBuy" Grid.Row="2" Grid.ColumnSpan="2" HorizontalOptions="Center"
Text="{StaticResource Btn_Pay}" BackgroundColor="Green" TextColor="White" CornerRadius="5" Margin="0,20,0,0" />
</Grid>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ScrollView>
</ContentPage>
Developer technologies .NET .NET MAUI
3 answers
Sort by: Most helpful
-
-
Anonymous
2023-07-20T08:46:19.2766667+00:00 Hello,
Please do not invoke async/await method in the constructor.
You can create an interface like following code.
/// <summary> /// Marks a type as requiring asynchronous initialization and provides the result of that initialization. /// </summary> public interface IAsyncInitialization { /// <summary> /// The result of the asynchronous initialization of this instance. /// </summary> Task Initialization { get; } }
And initialization is started in the constructor (when we call InitializeAsync) like edited following
ShoppingCartYViewModels.cs
code.public partial class ShoppingCartYViewModels : ObservableObject, IAsyncInitialization { [ObservableProperty] ObservableCollection<Plan> planY; public Task Initialization { get; private set; } public ShoppingCartYViewModels() { Initialization = InitializeAsync(); } private async Task InitializeAsync() { // Asynchronously initialize this instance. string filePath = "sabafon_data.json"; var carriers = await FileAssetHelper.ReadJsonFileAsync(filePath); PlanY = new ObservableCollection<Plan>(carriers["sabafon"].card.ToList()); } }
Here is a document about Task asynchronous programming model, you can refer to.
Best Regards,
Leon Lu
If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.
-
freudi freudi 1 Reputation point
2024-03-25T14:03:20.0733333+00:00 I have the same problem, only on Android. But I did'nt fill it with data in the constructor, I do it later on a button press in the UI with something like:
avm.LoadListFromDb((AuswahlViewModel.DataModus)dm); // very fast
myCollectionView.ItemsSource = avm.Sections; // extremly slow