Issue Populating CollectionView with ObservableCollection in .NET MAUI

Arnab Mukherjee 80 Reputation points
2025-03-06T18:02:38.5266667+00:00

Hi, I am facing an issue in my .NET MAUI application where I am trying to populate a CollectionView using an ObservableCollection<LeaveSummary> in my ViewModel. The data is correctly fetched, and I can see the ObservableCollection.Count in a Label, but the CollectionView does not display the data.

I will attach my ViewModel, Class, and XAML code for reference. Any guidance on what might be missing or incorrectly implemented would be appreciated.

Please Let me know if you need more details.

Screenshot 2025-03-06 233025.png

public class LeaveSummary
{
    public string Name { get; set; }
    public int TotalLeaveCount { get; set; }
    public int LeaveTaken { get; set; }
}
<?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:icon="clr-namespace:LeaveMatrix.Helpers"
             xmlns:vm="clr-namespace:LeaveMatrix.ViewModels"
             x:Class="LeaveMatrix.Views.HomePage"
             x:DataType="vm:HomePageViewModel"
             Title="Home"             
             BackgroundColor="#FFFFFF">
    
    <ScrollView>
        <Grid RowDefinitions="Auto,Auto">
            <Grid Grid.Row="0">
                <Image Source="navbar.png" 
               Aspect="Fill"  
               HorizontalOptions="Fill" 
               VerticalOptions="Fill" />
                <Frame BackgroundColor="Transparent"
               BorderColor="Transparent"
               Margin="10,20"
                    HorizontalOptions="Center" 
               VerticalOptions="Start">
                    <VerticalStackLayout HorizontalOptions="Fill" VerticalOptions="CenterAndExpand">
                        <Border StrokeShape="Ellipse" WidthRequest="150" HeightRequest="150" Stroke="Transparent">
                            <Image Source="{Binding CurrentUser.ProfileImageURL, FallbackValue='Loading...', Converter={StaticResource ImageUrlConverter}}"  HorizontalOptions="Center" />
                        </Border>
                        <BoxView HeightRequest="20" Background="Transparent" />
                        <Label Text="Welcome back," FontSize="18" TextColor="White" HorizontalOptions="Center"/>
                        <Label Text="{Binding CurrentUser.Name , FallbackValue='Loading...'}" FontSize="24" FontAttributes="Bold" TextColor="White" HorizontalOptions="Center" />
                    </VerticalStackLayout>
                </Frame>
            </Grid>
            <Grid Grid.Row="1">
                <VerticalStackLayout Padding="20" Spacing="15" Margin="0,0,0,5">
                    <!-- Dashboard Section -->
                    <Grid HorizontalOptions="FillAndExpand" VerticalOptions="Center">
                        <!-- Define two columns -->
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <!-- Label in the first column -->
                        <Label 
                            Text="Dashboard" 
                            FontSize="18" 
                            FontAttributes="Bold" 
                            TextColor="#333333" 
                            HorizontalOptions="Start" 
                            VerticalOptions="Center" 
                            Grid.Column="0" />
                        <Frame 
                            Grid.Column="1"
                            HorizontalOptions="End"
                            VerticalOptions="Center"
                            BackgroundColor="Transparent"
                            BorderColor="#00AFB9"
                            CornerRadius="20"
                            Padding="0"
                            HasShadow="False">
                            <HorizontalStackLayout Padding="10,0" Spacing="5" VerticalOptions="Center">
                                <Label 
                                    Text="Leave History" 
                                    FontSize="14" 
                                    TextColor="#00A9C9" />
                                <Label 
                                    Text="{x:Static icon:IconFontFaSolid.ArrowRight}" 
                                    FontFamily="FaSolid"
                                    FontSize="16" 
                                    TextColor="#00AFB9" 
                                    VerticalOptions="Center" />
                            </HorizontalStackLayout>
                        </Frame>
                    </Grid>
                    <Label Text="{Binding LeaveSummary.Count, StringFormat='Leave Count: {0}'}" FontSize="16" TextColor="Red"/> <!--getting value here-->
                    
<!--but not getting value here-->
                    <Grid ColumnDefinitions="*,*,*" RowDefinitions="Auto,Auto" ColumnSpacing="12" RowSpacing="12">
                                                
                        <CollectionView ItemsSource="{Binding LeaveSummary}">
                            <CollectionView.ItemTemplate>
                                <DataTemplate>
                                    <Frame Padding="10" Margin="5" CornerRadius="10" BorderColor="Gray">
                                        <VerticalStackLayout>
                                            <Label Text="{Binding Name}" FontSize="18" FontAttributes="Bold"/>
                                            <Label Text="{Binding TotalLeaveCount}" FontSize="16"/>
                                            <Label Text="{Binding LeaveTaken}" FontSize="16"/>
                                        </VerticalStackLayout>
                                    </Frame>
                                </DataTemplate>
                            </CollectionView.ItemTemplate>
                        </CollectionView>
                    </Grid>
                    <Grid HorizontalOptions="FillAndExpand" VerticalOptions="Center" Margin="0,0,0,10">
                        <!-- Define two columns -->
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <!-- Label in the first column -->
                        <Label 
                         Text="Colleague's on leave" 
                         FontSize="18" 
                         FontAttributes="Bold" 
                         TextColor="#333333" 
                         HorizontalOptions="Start" 
                         VerticalOptions="Center" 
                         Grid.Column="0" />
                        <Frame 
         Grid.Column="1"
         HorizontalOptions="End"
         VerticalOptions="Center"
         BackgroundColor="Transparent"
         BorderColor="#00AFB9"
         CornerRadius="20"
         Padding="0"
         HasShadow="False">
                            <HorizontalStackLayout Padding="10,0" Spacing="5" VerticalOptions="Center">
                                <Label 
                 Text="Full List" 
                 FontSize="14" 
                 TextColor="#00A9C9" />
                                <Label 
                 Text="{x:Static icon:IconFontFaSolid.ArrowRight}" 
                 FontFamily="FaSolid"
                 FontSize="16" 
                 TextColor="#00AFB9" 
                 VerticalOptions="Center" />
                            </HorizontalStackLayout>
                        </Frame>
                    </Grid>
                    <CollectionView ItemsLayout="HorizontalList" HeightRequest="120">
                        <CollectionView.ItemTemplate>
                            <DataTemplate>
                                <Frame BorderColor="#00AFB9" CornerRadius="10" Padding="10" WidthRequest="100" Margin="5">
                                    <VerticalStackLayout HorizontalOptions="Center" VerticalOptions="Center">
                                        <Image Source="user_placeholder.png" WidthRequest="50" HeightRequest="50" HorizontalOptions="Center" />
                                        <Label Text="{Binding Name}" FontSize="14" TextColor="#333333" HorizontalOptions="Center" />
                                        <Label Text="{Binding LeaveDate}" FontSize="12" TextColor="#666666" HorizontalOptions="Center" />
                                    </VerticalStackLayout>
                                </Frame>
                            </DataTemplate>
                        </CollectionView.ItemTemplate>
                    </CollectionView>
                </VerticalStackLayout>
            </Grid>
        </Grid>
    </ScrollView>
</ContentPage>
using CommunityToolkit.Mvvm.ComponentModel;
using LeaveMatrix.Models;
using LeaveMatrix.Services.Interfaces;
using System.Collections.ObjectModel;
namespace LeaveMatrix.ViewModels
{
    public partial class HomePageViewModel : BaseViewModel
    {
        [ObservableProperty]
        private User currentUser;
        [ObservableProperty]
        private ObservableCollection<LeaveSummary> leaveSummary;
        private readonly IHomeService _homeService;
        public HomePageViewModel(IHomeService homeService)
        {
            _homeService = homeService;
        }
        public async Task InitializeAsync()
        {
            await PopulateHomePage();
        }
        private async Task PopulateHomePage()
        {
            try
            {
                string token = await SecureStorage.GetAsync("AuthToken");
                if (!string.IsNullOrEmpty(token))
                {
                    var homePageResponse = await _homeService.GetHomaPage(token);
                    if (homePageResponse != null)
                    {
                        CurrentUser = homePageResponse.User;
                        LeaveSummary = new ObservableCollection<LeaveSummary>(homePageResponse.LeaveSummary);
                        await SecureStorage.SetAsync("UserId", homePageResponse.User.Id.ToString());
                    }
                }
            }
            catch (Exception ex)
            {
                await Shell.Current.DisplayAlert("Error", ex.Message, "OK");
            }
        }
    }
}

.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
3,981 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Leon Lu (Shanghai Wicresoft Co,.Ltd.) 80,606 Reputation points Microsoft External Staff
    2025-03-07T02:05:48.8666667+00:00

    Hello,

    Firstly, please open your HomePageViewModel, please make sure BaseViewModel extend the ObservableObject, if not, please make HomePageViewModel to inherit the ObservableObject.

    Then, please change private ObservableCollection<LeaveSummary> leaveSummary; to private ObservableCollection<LeaveSummary> leaveSummarys;, if you just called leaveSummary, generated a new LeaveSummary property that implements all of the logic needed for raising change notifications. It have the same name with your Model.

    Here is my edited HomePageViewModel

     public partial class HomePageViewModel : ObservableObject
        {
            [ObservableProperty]
            private User currentUser;
            [ObservableProperty]
            private ObservableCollection<LeaveSummary> leaveSummarys;
            private readonly IHomeService _homeService;
            public HomePageViewModel(IHomeService homeService)
            {
                _homeService = homeService;
            }
            public async Task InitializeAsync()
            {
                await PopulateHomePage();
            }
            private async Task PopulateHomePage()
            {
                try
                {
                    string token = await SecureStorage.GetAsync("AuthToken");
                    if (!string.IsNullOrEmpty(token))
                    {
                        var homePageResponse = await _homeService.GetHomaPage(token);
                        if (homePageResponse != null)
                        {
                            CurrentUser = homePageResponse.User;
                            LeaveSummarys = new ObservableCollection<LeaveSummary>(homePageResponse.LeaveSummary);
                            await SecureStorage.SetAsync("UserId", homePageResponse.User.Id.ToString());
                        }
                    }
                }
                catch (Exception ex)
                {
                    await Shell.Current.DisplayAlert("Error", ex.Message, "OK");
                }
            }
        }
    

    By the way, The Frame control is marked as obsolete in .NET MAUI 9, and will be completely removed in a future release. The Border control should be used in its place. For more information, see Border.

    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

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.