I managed to Bind a Picker to the values in a list I needed. On the same page as the picker I want a Label to display what I picked from the picker. I have a Display text in the picker, And an "id", which is a single char.
Here is the XAML:
<Label HorizontalTextAlignment="Center" VerticalTextAlignment="Center" Text="{Binding Source={x:Reference AVPUPicker}, Path=SelectedItem}" FontAttributes="Bold" FontSize="10" TextColor="LightBlue" Padding="0,0,0,0"/>
<Label HorizontalTextAlignment="Center" VerticalTextAlignment="Center" Text="{Binding Source={x:Reference AVPUPicker}, Path=ItemDisplayBinding}" FontAttributes="Bold" FontSize="16" TextColor="LightBlue" Padding="0,0,0,0"/>
<Picker x:Name="AVPUPicker" Title="Vælg tilstand" SelectedItem="{Binding KarakterId}" ItemDisplayBinding="{Binding ForklarendeTekst}" ItemsSource="{Binding AVPUListe}" IsVisible="True"/>
Data binding on the Picker is working as intended. I have tested both "KarakterId" and "ForklarendeTekst", and it does show the right values when Picker is activated. So data seems to be loaded in the picker.
I'm using x:Reference, Path to get to the property on the picker. However this is where it fails. I do get an output for the two X:Ref bindings in the label:
EWSMonitor.Models.AVPU
Xamarin.Forms.Binding
If I removed the binding on SelectedItem property, And manually type in some text value, the binding on the Label works. So the Picker works, And the the reference to the property seem to work, when manually typing something in, but when bounded, it breaks.
What do I miss?
Update:
I think I'm missing the INotifyOnChange part on my List. But how can I accomplish that? I'm creating the list in my ViewModel: public IList<AVPU> AVPUListe { get; } which references to the class AVPU I have created in my Model folder:
public class AVPU
{
public char KarakterId { get; set; }
public string ForklarendeTekst { get; set; }
}
I then add my selections to the AVPUListe:
AVPUListe = new ObservableCollection<AVPU>();
AVPUListe.Add(new AVPU { KarakterId = 'A', ForklarendeTekst = "Alert - Vågen" });
AVPUListe.Add(new AVPU { KarakterId = 'V', ForklarendeTekst = "Verbal - Tiltale" });
AVPUListe.Add(new AVPU { KarakterId = 'P', ForklarendeTekst = "Pain - Smertestimuli" });
AVPUListe.Add(new AVPU { KarakterId = 'U', ForklarendeTekst = "Unresponsive - Ukontaktbar" });
As jason's reply, you need to binding Picker's SelectedItem by ViewModel, I do one simple sample that you can take a look:
<Label
Padding="0,0,0,0"
FontAttributes="Bold"
FontSize="10"
HorizontalTextAlignment="Center"
Text="{Binding Source={x:Reference AVPUPicker}, Path=SelectedItem.KarakterId}"
TextColor="LightBlue"
VerticalTextAlignment="Center" />
<Label
Padding="0,0,0,0"
FontAttributes="Bold"
FontSize="16"
HorizontalTextAlignment="Center"
Text="{Binding Source={x:Reference AVPUPicker}, Path=SelectedItem.ForklarendeTekst}"
TextColor="LightBlue"
VerticalTextAlignment="Center" />
<Picker
x:Name="AVPUPicker"
Title="Vælg tilstand"
IsVisible="True"
ItemDisplayBinding="{Binding ForklarendeTekst}"
ItemsSource="{Binding AVPUListe}"
SelectedItem="{Binding selecteditem}" />
SelectedItem need to implement INotifyPropertyChanged to notify data change when you change picker selected index.
public class avpuviewmodel:ViewModelBase
{
public ObservableCollection<AVPU> AVPUListe { get; set; }
private AVPU _selecteditem;
public AVPU selecteditem
{
get { return _selecteditem; }
set
{
_selecteditem = value;
RaisePropertyChanged("selecteditem");
}
}
public avpuviewmodel()
{
AVPUListe = new ObservableCollection<AVPU>();
AVPUListe.Add(new AVPU { KarakterId = 'A', ForklarendeTekst = "Alert - Vågen" });
AVPUListe.Add(new AVPU { KarakterId = 'V', ForklarendeTekst = "Verbal - Tiltale" });
AVPUListe.Add(new AVPU { KarakterId = 'P', ForklarendeTekst = "Pain - Smertestimuli" });
AVPUListe.Add(new AVPU { KarakterId = 'U', ForklarendeTekst = "Unresponsive - Ukontaktbar" });
selecteditem = AVPUListe[0];
}
}
public class AVPU
{
public char KarakterId { get; set; }
public string ForklarendeTekst { get; set; }
}
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Finally, binding viewmodel to current contentpage.
public partial class Page3 : ContentPage
{
public Page3()
{
InitializeComponent();
this.BindingContext = new avpuviewmodel();
}
}
your VM needs to have a property to bind to SelectedItem
ObservableCollection<AVPU> AVPUListe { get; set; }
AVPU Selected { get; set; }
then your Picker would be
<Picker SelectedItem="{Binding Selected}" ... />
and your Label
<Label Text="{Binding Selected.ForklarendeTekst" ... />
Related
I have a list of room_ retrieved from Firebase Realtime Database. However:
How do I get the last-child data of each of those room_. Like the example in the image below: I want to get the result Key: Mqof3FYCrNdn0ipU5T8 for room_001_002, Key: MqofzCyjqQJ56BLiNHu for room_001_003 and display in CollectionView.
ListRoom.xaml
<CollectionView x:Name="listChats" ItemsSource="{Binding IteamGetRoomChats}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout VerticalOptions="FillAndExpand" Margin="0,0,0,2">
<StackLayout BindableLayout.ItemsSource="{Binding IteamGetRoomChatsChild}">
<Frame x:Name="Tap_chatdetail" HasShadow="False" Padding="12,10" BackgroundColor="#f5f4f4">
<Label Text="{Binding Content}" FontSize="13"/>
<Label Text="{Binding NameUser}" FontSize="13"/>
<Frame.GestureRecognizers>
<TapGestureRecognizer Command="{Binding viewdetailChat}" CommandParameter="{Binding RoomID}" />
</Frame.GestureRecognizers>
</Frame>
</StackLayout>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
ListRoom.xaml.cs
public ObservableCollection<GetRoomChats> IteamGetRoomChats { get; set; } = new ObservableCollection<GetRoomChats>();
public ObservableCollection<MyDatabaseRecord> IteamGetRoomChatsChild { get; set; } = new ObservableCollection<MyDatabaseRecord>();
List<GetRoomChats> listroomuser = new List<GetRoomChats>();
....
public Command viewdetailChat { get; set; }
....
public ListRoom()
{
LoadContentChat();
}
protected async void LoadContentChat()
{
BindingContext = this;
//Get room user success
var FirebaseClient = fc
.Child("RecordsChat")
.AsObservable<GetRoomChats>()
.Subscribe((dbevent) =>
{
foreach (var room in listroomuser)
{
if (dbevent.Key == room.RoomID)
{
IteamGetRoomChats.Add(dbevent.Object);
}
}
//How to get the last column of each of those room_
});
//End get room user success
viewdetailChat = new Command( async() => await Navigation.PushAsync(new DetailChats(//get roomid)));
}
Models
public class GetRoomChats
{
public string RoomID { get; set; }
}
public class MyDatabaseRecord
{
public string UID { get; set; }
public string NameUser { get; set; }
public string Content { get; set; }
public string RoomID { get; set; }
}
How can I get the roomid to execute the Command without going through any ViewModel.
viewdetailChat = new Command( async() => await Navigation.PushAsync(new DetailChats(//get roomid)));
Thanks for all the help. Thanks
Update
Questions 1:
var FirebaseClient = fc
.Child("RecordsChat")
.AsObservable<GetRoomChats>()
.Subscribe((dbevent) =>
{
foreach (var room in listroomuser)
{
if (dbevent.Key == room.RoomID)
{
IteamGetRoomChats.Add(dbevent.Object);
//Get last-child off room
var query = fc.Child("RecordsChat").Child(dbevent.Key).OrderByKey().LimitToLast(1);
var get = query.AsObservable<MyDatabaseRecord>().Subscribe((dbeventchild) =>
{
IteamGetRoomChatsChild.Add(dbeventchild.Object);//get Null
});
}
}
});
I have a profile view-model that in it's constructor calls the DB for the user that just logged. It works fine but if I delay it by 3s then I assume one of the threads continues and creates the view with nothing inside. I use a data template selector to construct the view and if I delay the task then the view will not render anything. Again, if I don't delay it works fine but I need to make sure that it will work if the server takes longer to respond and 3s is not that much in some cases
here is my view model
public class ProfileViewModel: BaseViewModel
{
private ObservableCollection<Stylist> users;
public ObservableCollection<Stylist> Users
{
get => users;
set
{
users = value;
OnPropertyChanged();
}
}
private Stylist user;
public Stylist User { get => user; set { user = value; OnPropertyChanged(); } }
private bool isStylist;
public AsyncCommand TestCommand { get; set; }
public ProfileViewModel()
{
IsBusy = true;
TestCommand = new AsyncCommand(Test);
Users = new ObservableCollection<Stylist>();
Task.Run(async () =>
{
int id = ((App)App.Current).ID;
if (!((App)App.Current).IsStylist)
{
var user = await DB.GetUser(id);
User = CopyUserToStylist(user);
}
else User = await DB.GetStylist(id);
isStylist = User.IsStylist;
await Task.Delay(3000); // without this line everything is ok
Users.Add(User);
OnPropertyChanged(nameof(Users));
IsBusy = false;
});
}
the view
<ContentPage.Resources>
<DataTemplate x:Key="UserTemplate">
<StackLayout>
<Label Text="user logged"/>
<Label Text="{Binding Name}"/>
</StackLayout>
</DataTemplate>
<DataTemplate x:Key="StylistTemplate">
<StackLayout>
<Label Text="stylist logged"/>
<Label Text="{Binding Name}"/>
<Label Text="{Binding Location}"/>
<Button Text="Test stylist"
Command="{Binding TestCommand}"/>
</StackLayout>
</DataTemplate>
<local:UserTypeSelector
x:Key="personDataTemplateSelector"
StylistTemplate="{StaticResource StylistTemplate}"
UserTemplate="{StaticResource UserTemplate}" />
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Margin="10"
BindableLayout.ItemTemplateSelector="{StaticResource personDataTemplateSelector}"
BindableLayout.ItemsSource="{Binding Users}">
<Label Text="FML"/>
<Label Text="Loading"
IsVisible="{Binding IsBusy}"/>
<Button Text="Test"
Command="{Binding TestCommand}"/>
</StackLayout>
</ContentPage.Content>
and the db calls
public static async Task<User> GetUser(int id)
{
await Init();
return await db.Table<User>().Where(x => x.id == id).FirstAsync();
}
public static async Task<Stylist> GetStylist(int id)
{
await Init();
return await db.Table<Stylist>().Where(x => x.id == id).FirstAsync();
}
if I don't delay it works fine but I need to make sure that it will work if the server takes longer to respond and 3s is not that much in some cases
If you use Await in Task, the code starting from Await will be in another thread, not in main thread, so the UI will be not updated.
You can use Device.BeginInvokeOnMainThread(Action) Method to update UI by changing data source.
I do one sample that you can take a look.
<StackLayout Margin="10" BindableLayout.ItemsSource="{Binding Users}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding name}" />
<Label Text="{Binding age}" />
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
public partial class Page52 : ContentPage
{
public Page52()
{
InitializeComponent();
this.BindingContext = new ProfileViewModel();
}
}
public class ProfileViewModel:ViewModelBase
{
public ObservableCollection<user1> Users { get; set; }
public ProfileViewModel()
{
Users = new ObservableCollection<user1>();
Task.Run(async()=> {
user1 user = new user1() { name = "cherry", age = 18 };
await Task.Delay(3000);
Device.BeginInvokeOnMainThread(()=> {
Users.Add(user);
});
});
}
}
public class user1
{
public string name { get; set; }
public int age { get; set; }
}
I have a collectionview which has a [Label(day of the week] - [checkbox] - [picker with times].
I want the user to be able to select a day and time, after that I want to then pass those values to my database. So far I am able to select the day and pass this value on. However I am struggling to refence the value in the picker. I think this is due to it being a list in my object. I have tried booking.Listtimes but that is just a list. I want the value selected.
My ViewModel:
public class RepeatMonthly
{
public string Day { get; set; }
public bool Selected { get; set; }
public List<WalkTimes> _ListTimes { get; set; }
}
private WalkTimes _selectedTimes;
public WalkTimes SelectedTimes
{
get
{
return _selectedTimes;
}
set
{
SetProperty(ref _selectedTimes, value);
}
}
public ObservableCollection<RepeatMonthly> DayList { get; set; }
public CreateWeeklyScheduleViewModel()
{
ListTimes = WalkTimesService.GetTimes().OrderBy(c => c.Key).ToList();
DayList = new ObservableCollection<RepeatMonthly>()
{
new RepeatMonthly(){Day="Every Monday", Selected = false, _ListTimes = ListTimes},
new RepeatMonthly(){Day="Every Tuesday", Selected = false, _ListTimes = ListTimes},
new RepeatMonthly(){Day="Every WednesDay", Selected = false, _ListTimes = ListTimes},
new RepeatMonthly(){Day="Every Thursday", Selected = false, _ListTimes = ListTimes},
new RepeatMonthly(){Day="Every Friday", Selected = false, _ListTimes = ListTimes},
new RepeatMonthly(){Day="Every Saturday", Selected = false, _ListTimes = ListTimes},
new RepeatMonthly(){Day="Every Sunday", Selected = false, _ListTimes = ListTimes}
};
source = new ObservableCollection<PetProfile>();
}
My Xaml:
<CollectionView x:Name="RepeatCollectionView" HorizontalOptions="Center" ItemsSource="{Binding DayList}" HeightRequest="350">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="0" RowDefinitions="25, 20" ColumnDefinitions="*,*">
<Label Text="{Binding Day}" FontAttributes="Bold" FontSize="Medium"
Margin="5,0"
VerticalTextAlignment="Center" HorizontalTextAlignment="Start"/>
<CheckBox x:Name="SelectDayCheckBox" Grid.Row="0" HorizontalOptions="End" IsChecked="{Binding Selected, Mode=TwoWay}" BindingContext="{Binding .}" CheckedChanged="SelectDayCheckBox_CheckedChanged"/>
<Picker x:Name="SelectTimeOfWalkPicker" Title="--Select Walk Start Time--" Grid.Column="1" ItemsSource="{Binding _ListTimes}" ItemDisplayBinding="{Binding Value}" VerticalTextAlignment="Center" HorizontalTextAlignment="Center" SelectedItem="{Binding SelectedTimes}" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
my .cs page:
private async void SubmitBtn_Clicked(object sender, EventArgs e)
{
foreach (RepeatMonthly booking in (BindingContext as CreateWeeklyScheduleViewModel).DayList)
{
if (booking.Selected)
{
await passtoDataBase(booking.Day, "where time variable goes");
}
}
await DisplayAlert("Success", "Booked Successfully", "OK");
await Shell.Current.GoToAsync($"//{nameof(MyBookingsPage)}");
}
properties of WalkTimes object:
public class WalkTimes
{
public int Key { get; set; }
public string Value { get; set; }
}
I have a question here (I imagine it is for beginners: P).
I have a listview and a searchbar already working. I can make the right filter.
Then my question comes in, this listview has more than one column.
I can't think of a way to make 2 complementary filters.
For example:
Filter column 1 and then filter the result of that initial filter by column 2 (with another searchbar), that is, a filter on top of another filter.
My ListViewItem is like this with the filter:
C#
void InitList()
{
Items = new List<ListViewItem>
{
new ListViewItem { Name = "Guilherme", Bairro = "BOTAFOGO"},
new ListViewItem { Name = "João", Bairro = "FLAMENGO"},
new ListViewItem { Name = "Maria", Bairro = "CENTRO"}
}
}
void InitSearchBarBloco()
{
sb_search_bloco.TextChanged += (s, e) => FilterItem(sb_search_bloco.Text);
sb_search_bloco.SearchButtonPressed += (s, e) =>
FilterItem(sb_search_bloco.Text);
}
private void FilterItem(string filter)
{
exampleListView.BeginRefresh();
if (string.IsNullOrWhiteSpace(filter))
{
exampleListView.ItemsSource = Items;
}
else
{
exampleListView.ItemsSource = Items.Where(x => x.Name.ToLower().Contains(filter.ToLower()));
}
exampleListView.EndRefresh();
}
XAML
<SearchBar x:Name="sb_search_bloco" Placeholder="Nome..." />
<ListView x:Name="exampleListView" RowHeight="22" SelectedItem="{Binding Name}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell >
<Grid>
<Label Text="{Binding Name}" LineBreakMode="TailTruncation" />
<Label Grid.Column="1" Text="{Binding Bairro}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
With this structure I can implement this ... "filtrate filter"?
thanks
I guess the below code should do fine for you. You just need to alter your linq code inside the FilterItem(string filter) method to achieve your requirement.
Note:
I have used OR condition inside the where clause to search if the enter text is available in both Name and Bairro. However, you can modify the condition as you require.
private void FilterItem(string filter)
{
exampleListView.BeginRefresh();
if (string.IsNullOrWhiteSpace(filter))
{
exampleListView.ItemsSource = Items;
}
else
{
//Alter the condition like below or based on requirement to achieve the desired result.
exampleListView.ItemsSource = Items.Where(x => x.Name.ToLower().Contains(filter.ToLower()) || x.Bairro.ToLower().Contains(filter.ToLower()));
}
exampleListView.EndRefresh();
}
I make a sample code for your referece.
xmal:
<StackLayout>
<StackLayout>
<SearchBar x:Name="sb_search_bloco" Placeholder="Nome..." TextChanged="sb_search_bloco_TextChanged"/>
<SearchBar x:Name="searchBar2" Margin="0,10" TextChanged="searchBar2_TextChanged" />
</StackLayout>
<ListView
x:Name="exampleListView"
RowHeight="22"
ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Label LineBreakMode="TailTruncation" Text="{Binding Name}" />
<Label Grid.Column="1" Text="{Binding Bairro}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
ListViewItem.cs
public class ListViewItem
{
public string Name { get; set; }
public string Bairro { get; set; }
}
MainPage.xml.cs
public partial class MainPage : ContentPage
{
public List<ListViewItem> Items { get; set; }
public MainPage()
{
InitializeComponent();
Items = new List<ListViewItem>
{
new ListViewItem { Name = "AAAA", Bairro = "BBCFS"},
new ListViewItem { Name = "ABBB", Bairro = "SSDCA"},
new ListViewItem { Name = "AAAA", Bairro = "AAAD"},
new ListViewItem { Name = "CCCC", Bairro = "SSS"},
new ListViewItem { Name = "DAAB", Bairro = "CCC"},
new ListViewItem { Name = "DDDC", Bairro = "QWDAS"}
};
this.BindingContext = this;
}
private void sb_search_bloco_TextChanged(object sender, TextChangedEventArgs e)
{
exampleListView.ItemsSource = FilterItem1(e.NewTextValue);
}
IEnumerable<ListViewItem> FilterItem1(string filter = null)
{
if (string.IsNullOrEmpty(filter))
return Items;
return Items.Where(p => p.Name.StartsWith(filter));
}
private void searchBar2_TextChanged(object sender, TextChangedEventArgs e)
{
exampleListView.ItemsSource = FilterItem2(e.NewTextValue);
}
IEnumerable<ListViewItem> FilterItem2(string filter = null)
{
if (string.IsNullOrEmpty(filter))
return Items;
return Items.Where(p => p.Bairro.StartsWith(filter));
}
}
I am trying to bind a response to a custom ListView in Xamarin.Forms but the ListView remains blank even when the ObservableCollection contains results. Please point out my mistake in the code below.
In the below code, I am trying to achieve following result -
The response received from Firebase is serialized and then a custom calendar is created based on the response.
To create the calendar, I am using a Model which will contain all the necessary bindings to be displayed in the View. e.g Color, title, counts etc.
I am using Prism MVVM architecture for building the app.
View
<ListView ItemsSource="{Binding ListItems}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame BorderColor="LightGray" Padding="5">
<StackLayout Orientation="Horizontal">
<!--<BoxView BackgroundColor="{Binding HighlightColor}" WidthRequest="10"/>-->
<Label Text="{Binding Date}" FontSize="Medium" Margin="20,0,0,0"/>
<Label Text="{Binding Day}" FontSize="Medium" Margin="20,0,0,0"/>
<Label Text="{Binding LeaveCount}" HorizontalOptions="EndAndExpand" HorizontalTextAlignment="End"/>
</StackLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ViewModel
public ObservableCollection<CalendarItem> ListItems { get; set; }
public LeaveViewerPageViewModel(INavigationService navigationService, IFirebaseService firebaseService)
: base(navigationService, firebaseService)
{
Title = "View Leaves";
ViewCommand = new DelegateCommand(ViewLeaves);
}
private async void ViewLeaves()
{
ListItems = new ObservableCollection<CalendarItem>();
var x = await FirebaseService.GetAll(_month, _year);
foreach (var item in x)
{
ListItems.Add(item);
}
}
Service
public async Task<List<CalendarItem>> GetAll( string month, string year)
{
List<CalendarItem> ItemList = new List<CalendarItem>();
int iterationLimit = DateTime.DaysInMonth(int.Parse(year), (DateTime.ParseExact(month.Substring(0, 3), "MMM", CultureInfo.InvariantCulture)).Month);
for (int i = 1; i <= iterationLimit; i++)
{
CalendarItem ITEM = new CalendarItem();
DateTime dateTime = new DateTime(int.Parse(year), DateTime.ParseExact(month.Substring(0, 3), "MMM", CultureInfo.InvariantCulture).Month, i);
var res = await GetLeavesAsync(i, month, year);
ITEM.Date = dateTime.Day.ToString();
ITEM.Day = dateTime.DayOfWeek.ToString();
ITEM.LeaveCount = res.Count;
ITEM.Leaves = res;
if (res.Count > 0)
ITEM.HighlightColor = res.Count < 5 ? System.Drawing.Color.Yellow : System.Drawing.Color.Tomato;
ItemList.Add(ITEM);
}
return ItemList;
}
Model
public class CalendarItem
{
public Color HighlightColor { get; set; }
public string Date { get; set; }
public string Day { get; set; }
public int LeaveCount { get; set; }
public List<LeaveDetail> Leaves { get; set; }
}
Based on the code you have here there are actually a couple of issues:
1) Your ListItems property in the ViewModel is not itself implementing INotifyPropertyChanged.
public class ViewAViewModel : BindableBase
{
private ObservableCollection<CalendarItem> _listItems;
public ObservableCollection<CalendarItem> ListItems
{
get => _listItems;
set => SetProperty(ref _listItems, value);
}
}
2) You are newing up a ListItems in the ViewLeaves method and then adding each item one at a time. The result here is that if you followed the first step when you set ListItems it would try to update the UI, and then every time you add an item it will try to update the UI.
3) You have two options for optimizing this:
Use ObservableRangeCollection which James Montemagno has in his MvvmHelpers library. This will allow you to new up the collection in the ctor and then simply dump a collection in like:
private async void ViewLeaves()
{
ListItems.ReplaceRange(await FirebaseService.GetAll(_month, _year));
}
Simply implement the property as shown in the first issue I pointed out but change it to IEnumerable<CalendarItem> and simply set it like:
private async void ViewLeaves()
{
ListItems = await FirebaseService.GetAll(_month, _year);
}
Please try modifying your ListItems as follows:-
private ObservableCollection<CalendarItem> _listItems = new ObservableCollection<CalendarItem>();
public ObservableCollection<CalendarItem> ListItems
{
get => _listItems;
set => SetProperty(ref _listItems, value);
}