MauiDays is a .NET MAUI library that provides a customizable month and day calendar popup selector, along with a calendar page. It allows developers to easily add date selection functionality to their .NET MAUI apps.
$ dotnet add package ControlDays.Calendar.MauiMauiDays is a .NET MAUI library that provides a customizable month and day calendar popup selector, along with a calendar page. It allows developers to easily add date selection functionality to their .NET MAUI apps.
The library has a dependency on Mopups, which is used for the month and day calendar popup selector functionality. Note that if you only need the calendar page, you do not need to install Mopups.

| Platform | Version | Popups Availability | Calendar Page Availability |
|---|---|---|---|
| iOS | 14.0 and higher | ✅ | ✅ |
| Android | 5.0 and higher | ✅ | ✅ |
| Windows | 10.0.17763.0 and higher | ❌ | ✅ |
| macOS | 10.15 and higher | ✅ | ✅ |
To use this package, simply install it in your .NET MAUI project using NuGet. In Visual Studio, you can do this by right-clicking on your project and selecting "Manage NuGet Packages". From there, search for "ControlDays.Calendar.Maui" and install the latest version.
dotnet add package ControlDays.Calendar.Maui
Please, remember that you need to install and configure the Mopups nuget package. This dependency is necessary to use the popups.
dotnet add package Mopups
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureMopups();
return builder.Build();
}
You can use the Calendar popups with a fluent syntax, a programming style that focuses on making code more readable. By using the fluent syntax, it becomes easier for the developer to understand and modify the behavior of the popups, making it a more user-friendly and efficient approach to programming.
Keep in mind that:
Here's an example:
var popup = new SingleDaySelectorCalendarPopup
(
callbackCancel: async () => { await MopupService.Instance.PopAsync(); },
callbackConfirm: async (date) => { await OnDateChanged(date); }
)
.Build();
await MopupService.Instance.PushAsync(popup);
and the same for the Month selector:
var popup = SingleMonthSelectorCalendarPopup
(
callbackCancel: async () => { await MopupService.Instance.PopAsync(); },
callbackConfirm: async (date) => { await OnDateChanged(date); }
)
.Build();
await MopupService.Instance.PushAsync(popup);
Below, you will find a list of available options for the Day Selector popup and Month Selector popup:
If you are using the Calendar Day selector, you can use the function SetDaysOfWeekFontFamily property too. BUT remember: for technical reasons you need to call this function first, right after instantianting the popup, that means:
var popup = new SingleDaySelectorCalendarPopup
(
callbackCancel: async () => { await MopupService.Instance.PopAsync(); },
callbackConfirm: async (date) => { await OnDateChanged(date); }
)
.SetDaysOfWeekFontFamily(LabelDaysOfWeekFontFamily())
...
.Build();
await MopupService.Instance.PushAsync(popup);
Now that you know all functions to customize your popups, let's see an example with the fluent syntax:
public static class CalendarPopupBuilder
{
public static BaseCalendarPopup SingleMonth(Action<DateOnly> callbackConfirm)
{
return new SingleMonthSelectorCalendarPopup(async () => { await MopupService.Instance.PopAsync(); }, callbackConfirm)
.SetPopupBackgroundColor(PopupBackgroundColor())
.SetCalendarBackgroundColor(CalendarBackgroundColor())
.SetPrimaryColor(PrimaryColor())
.SetHeaderFontFamily(HeaderFontFamily())
.SetConfirmButtonColor(ColorForConfirmButton())
.SetTextCancel("CANCEL")
.SetConfirmButtonTextColor(SelectedConfirmButtonTextColor())
.SetCancelFontFamily(CancelFontFamily())
.SetCulture(Culture())
.SetSelectedBackgroundColor(SelectedBackgroundColor())
.SetSelectedLabelColor(SelectedLabelColor())
.SetLabelFontFamily(LabelFontFamily());
}
public static BaseCalendarPopup SingleDay(Action<DateOnly> callbackConfirm)
{
return new SingleDaySelectorCalendarPopup(async () => { await MopupService.Instance.PopAsync(); }, callbackConfirm)
.SetDaysOfWeekFontFamily(LabelDaysOfWeekFontFamily())
.SetPopupBackgroundColor(PopupBackgroundColor())
.SetCalendarBackgroundColor(CalendarBackgroundColor())
.SetPrimaryColor(PrimaryColor())
.SetHeaderFontFamily(HeaderFontFamily())
.SetConfirmButtonColor(ColorForConfirmButton())
.SetTextCancel("CANCEL")
.SetConfirmButtonTextColor(SelectedConfirmButtonTextColor())
.SetCancelFontFamily(CancelFontFamily())
.SetCulture(Culture())
.SetSelectedBackgroundColor(SelectedBackgroundColor())
.SetSelectedLabelColor(SelectedLabelColor())
.SetLabelFontFamily(LabelFontFamily());
}
private static Color ColorForConfirmButton() => Color.FromArgb(Application.Current.IsLightMode() ? "#40806A" : "#00D46A");
private static Color PrimaryColor() => Application.Current.IsLightMode() ? Colors.Black : Colors.White;
private static Color SelectedBackgroundColor() => Application.Current.IsLightMode() ? Colors.Black : Colors.White;
private static Color SelectedLabelColor() => Application.Current.IsLightMode() ? Colors.White : Colors.Black;
private static Color SelectedConfirmButtonTextColor() => Application.Current.IsLightMode() ? Colors.White : Colors.Black;
private static Color CalendarBackgroundColor() => Application.Current.IsLightMode() ? Colors.White : Application.Current.GetDarkMode();
private static Color PopupBackgroundColor() => Color.FromArgb("#80A1A1A1");
private static string CancelFontFamily() => "OpenSansRegular";
private static string HeaderFontFamily() => "OpenSansSemibold";
private static string LabelFontFamily() => "OpenSansRegular";
private static string LabelDaysOfWeekFontFamily() => "OpenSansRegular";
private static CultureInfo Culture() => CultureInfo.CurrentCulture;
}
public partial class CalendarDashboardViewModel : ObservableObject
{
[RelayCommand]
public static async Task SingleMonth()
{
var today = DateOnly.FromDateTime(DateTime.Today);
var popup = CalendarPopupBuilder
.SingleMonth(async (date) =>
{
await Callback(date, true);
})
.SetDate(today)
.SetMinimumDate(new DateOnly(today.Year - 1, today.Month, 7))
.SetMaximumDate(new DateOnly(today.Year + 1, today.Month, 7))
.Build();
await MopupService.Instance.PushAsync(popup);
}
}
My customizable calendar page gives you the freedom to create a personalized interface with a customizable calendar and IView of your choice. The page accepts a parameter in the form of a command, which is executed whenever a user chooses a day. This powerful combination allows you to display detailed information about a selected day, or trigger a specific event.
To use the Calendar page, you need to add a reference to the namespace in your XAML file:
xmlns:page="clr-namespace:MauiDays.Views.Pages;assembly=MauiDays"
Here's an example:
<page:SingleDaySelectorPage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:page="clr-namespace:MauiDays.Views.Pages;assembly=ControlDays.Calendar.Maui"
x:Class="Packages.MAUI.App.Views.Calendar.SingleDaySelectorPage"
OnDaySelectedCommand="{Binding SelectedDayCommand}">
<page:SingleDaySelectorPage.MyContent>
<VerticalStackLayout Margin="0,40,0,0">
<Label Text="YOU CAN CREATE ANY KIND OF IVIEW INSIDE THE PROPERTY MyContent" />
</VerticalStackLayout>
</page:SingleDaySelectorPage.MyContent>
</page:SingleDaySelectorPage>
Don't forget to change the Code-behind
public partial class SingleDaySelectorPage : MauiDays.Views.Pages.SingleDaySelectorPage
{
public SingleDaySelectorPage()
{
InitializeComponent();
}
}
ATTENTION: The next two properties are required. Don't forget to set them:
Now that you know all properties to customize your calendar pages, let's see an example:
<page:SingleDaySelectorPage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:page="clr-namespace:MauiDays.Views.Pages;assembly=ControlDays.Calendar.Maui"
xmlns:viewModel="clr-namespace:Packages.MAUI.App.ViewModels.Calendar"
xmlns:s="clr-namespace:System;assembly=mscorlib"
x:Class="Packages.MAUI.App.Views.Calendar.SingleDaySelectorPage"
x:DataType="viewModel:SingleDaySelectorViewModel"
OnDaySelectedCommand="{Binding SelectedDayCommand}"
MinimumDate="{Binding MinimumDate}"
MaximumDate="{Binding MaximumDate}"
PrimaryColor="{AppThemeBinding Light=Black, Dark=White}"
SelectedBackgroundColor="{AppThemeBinding Light=Black, Dark=White}"
SelectedDayColor="{AppThemeBinding Light=White, Dark=Black}"
HeaderFontFamily="OpenSansRegular"
DaysOfWeekFontFamily="OpenSansRegular"
DaysFontFamily="OpenSansRegular"
DaysWithEvents="{Binding DaysWithEvents}"
HighlightColor="{AppThemeBinding Light=#DC143C, Dark=#F22613}"
Culture="{Binding Culture}"
Date="{Binding Date}">
<page:SingleDaySelectorPage.MyContent>
<VerticalStackLayout Margin="0,40,0,0">
<Label Text="Current data:" FontSize="18" FontAttributes="Bold" HorizontalOptions="Center" TextColor="{AppThemeBinding Light=Black, Dark=White}" />
<Label Text="{Binding Date, StringFormat='{}{0:MMMM/dd/yyyy}'}" HorizontalOptions="Center" FontSize="16" TextColor="{AppThemeBinding Light=Black, Dark=White}" />
</VerticalStackLayout>
</page:SingleDaySelectorPage.MyContent>
</page:SingleDaySelectorPage>
public partial class SingleDaySelectorViewModel : ObservableObject
{
[ObservableProperty]
public DateOnly date;
[ObservableProperty]
public DateOnly minimumDate;
[ObservableProperty]
public DateOnly maximumDate;
[ObservableProperty]
public IList<int> daysWithEvents;
[ObservableProperty]
public CultureInfo culture;
public SingleDaySelectorViewModel()
{
Culture = CultureInfo.CurrentCulture;
var today = DateOnly.FromDateTime(DateTime.Today);
Date = today;
MinimumDate = new DateOnly(today.Year, today.Month - 1, 7);
MaximumDate = new DateOnly(today.Year, today.Month + 1, 7);
DaysWithEvents = new List<int> { 6, 11, 23, 24 };
}
[RelayCommand]
public void SelectedDay(DateOnly date)
{
Date = date;
}
}
MauiDays is released under the MIT License. See LICENSE.txt for details.