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);
}
}
}
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>