Search code examples
c#xamarin.formscollectionview

CollectionView Throws InvalidCastException or empty with ObservableCollection


When I load my code with the observablecollection i get a

System.InvalidCastException: 'Specified cast is not valid.'

before i made some changes to the code it just showed me an empty list (which is just as puzzling since the only thing i changed is move the observable collection from being encapsulated to showing like it does here)

I tried using a list instead of ObservableCollection, comes back empty.

Changing CollectionView to a ListView makes everything work perfectly.

I have fody implemented and autofac in the background, implementations come from a book.

xaml:

<CollectionView x:Name="CalanderDays"
                            ItemsSource="{Binding daysInCurrentCalanderView}"
                            Grid.Row="1"
                            Grid.ColumnSpan="7">
                <CollectionView.ItemTemplate>
                <DataTemplate>
                    <ViewCell Height="48">
                        <Grid Grid.Column="1">
                             <BoxView Color="Green"
                                      CornerRadius="124"/>
                             <Label Text="{Binding WorkDay.Day}"
                                    FontSize="18"
                                    TextColor="White"
                                    FontAttributes="Bold"
                                    HorizontalOptions="Center"
                                    VerticalOptions="Center"/>
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

ViewModel:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using DatePickerEmbedded.Models;
using DatePickerEmbedded.Repositories;
using Xamarin.Forms;

namespace DatePickerEmbedded.ViewModels
{
    public class MainViewCalanderViewModel : ViewModel
    {

        private readonly WorkDaysRepository db;


        private IList<WorkDayViewModel> loadingDays;

        public ObservableCollection<WorkDayViewModel> daysInCurrentCalanderView
        {
            get;
            private set;
        }

        private DateTime lastDateChosen = DateTime.Today;
        public MainViewCalanderViewModel(WorkDaysRepository db)
        {
            this.db = db;
            Task.Run(async () => await LoadDays());
        }


        private async Task LoadDays()
        {
            loadingDays = new List<WorkDayViewModel>();
            DateTime firstDayOfMonth = new DateTime(lastDateChosen.Year, lastDateChosen.Month, 1);
            int offset = (int)firstDayOfMonth.DayOfWeek;

            int numberOfDaysShown = (int)(Math.Ceiling((DateTime.DaysInMonth(lastDateChosen.Year, lastDateChosen.Month) + (double)offset) / 7) * 7);
            
            for (int i = -offset; i <= numberOfDaysShown - offset; i++)
            {
                DateTime workingDay = firstDayOfMonth.AddDays(i);
                WorkDay dayToFill = await db.GetDay(workingDay);


                if (dayToFill == null || workingDay.Month != firstDayOfMonth.Month)
                {
                    dayToFill = new WorkDay() { ClockIn = workingDay };
                    loadingDays.Add(new WorkDayViewModel(dayToFill));
                }
                else
                {
                    loadingDays.Add(new WorkDayViewModel(dayToFill));
                }
                
            }

            daysInCurrentCalanderView = new ObservableCollection<WorkDayViewModel>(loadingDays);        
        }
    }
    

}


Solution

  • The problem was with the xaml, you can not add <ViewCell> in CollectionView.DataTemplate, I suggest you can use a <StackLayout> or <Grid> in <DataTemplate>.

    <CollectionView x:Name="CalanderDays"
                            ItemsSource="{Binding daysInCurrentCalanderView}"
                            Grid.Row="1"
                            Grid.ColumnSpan="7">
                <CollectionView.ItemTemplate>
                    <DataTemplate>
                       
                            <Grid Grid.Column="1">
                                <BoxView Color="Green"
                                      CornerRadius="124"/>
                                <Label Text="{Binding WorkDay.Day}"
                                    FontSize="18"
                                    TextColor="White"
                                    FontAttributes="Bold"
                                    HorizontalOptions="Center"
                                    VerticalOptions="Center"/>
                            </Grid>
                       
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>