Performance Issue with CollectionView in .NET MAUI

Asem AS 50 Reputation points
2023-07-19T09:01:54.0666667+00:00

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>
.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
2,870 questions
{count} votes

3 answers

Sort by: Most helpful
  1. Leon Lu (Shanghai Wicresoft Co,.Ltd.) 68,656 Reputation points Microsoft Vendor
    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.

    0 comments No comments

  2. 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

    0 comments No comments

  3. Stephane Louge 0 Reputation points
    2024-03-28T21:49:25.4833333+00:00

    Don't put your collectionview inside a scrollview. This remove virtualization by render the whole list items.

    0 comments No comments