TL;DR: Build a monthly weather forecast calendar in .NET MAUI Scheduler by binding weather data, customizing month cell templates, and adding temperature unit switching. Includes value converters and XAML customization for a rich UI experience.
Creating visually rich and interactive UI components is essential for modern mobile applications. In this tutorial, we’ll walk through how to design a monthly weather forecast calendar using the Syncfusion .NET MAUI Scheduler control. This calendar will display daily weather icons, high/low temperatures, and temperature units in a clean monthly view.
Let’s dive in!
Prerequisites
Before you begin:
- Install .NET MAUI and set up your development environment.
- Familiarize yourself with the Scheduler control basics.
- Ensure you have a working MVVM setup for data binding.
Step 1: Define the weather forecast model
Start by creating a model to represent daily weather data. This model will include:
- Date of the forecast
- High and low temperatures
- Weather icon
- Location (optional)
- Temperature unit (Fahrenheit or Celsius)
- Unit symbol (°F or °C)
It acts as the data model used to populate and display weather information in the calendar.
WeatherForecast.cs
{
public DateTime Date { get; set; }
public int HighTemp { get; set; }
public int LowTemp { get; set; }
public string WeatherIcon { get; set; }
public TemperatureUnit Unit { get; set; }
}
public enum TemperatureUnit
{
Fahrenheit,
Celsius
}
Step 2: Generate weather data in the ViewModel
The GenerateWeatherData() method populates a collection with simulated weather data around the selected month.
Key tasks:
- Clears existing data to avoid duplication.
- Calculates a date range covering 1.5 months before and after the selected month.
- Generates random weather conditions and icons for each day using a seeded randomizer.
- Creates temperature values in Fahrenheit and converts them to Celsius if needed.
- Builds a WeatherForecast object for each day with all relevant details.
- Stores the forecast in a list for display and a dictionary for quick look up by date.
This method ensures the calendar has complete and consistent weather data for all visible days.
WeatherForecastViewModel.cs
private void GenerateWeatherData()
{
WeatherData.Clear();
var startDate = SelectedDate.AddMonths(-1);
var endDate = SelectedDate.AddMonths(1);
var random = new Random();
for (var date = startDate; date <= endDate; date = date.AddDays(1))
{
WeatherData.Add(new WeatherForecast
{
Date = date,
HighTemp = random.Next(60, 100),
LowTemp = random.Next(40, 60),
WeatherIcon = GetRandomIcon(),
Unit = SelectedTemperatureUnit
});
}
}
Data refresh on date change
Bind SelectedDate to the Scheduler’s DisplayDate so the data refreshes when the user navigates:
WeatherForecastViewModel.cs
public DateTime SelectedDate
{
get => _selectedDate;
set
{
_selectedDate = value;
OnPropertyChanged();
GenerateWeatherData();
}
}
This triggers the GenerateWeatherData() method, which regenerates the weather data for the new date range. This ensures the calendar always shows up-to-date weather information based on the currently viewed month.
Note: The weather data shown in this example is static and provided for demonstration purposes only.
Step 3: Add the Scheduler control
Configure the Scheduler to display a Month view without default appointments. It binds to a WeatherForecastViewModel class, displays the selected date, and hides the default appointment visuals, allowing you to fully customize each day cell. This is ideal for displaying weather data, such as icons and temperatures.
MainPage.xaml
<scheduler:SfScheduler View="Month"
DisplayDate="{Binding SelectedDate, Mode=TwoWay}">
<scheduler:SfScheduler.MonthView>
<scheduler:SchedulerMonthView AppointmentDisplayMode="None"/>
</scheduler:SfScheduler.MonthView>
</scheduler:SfScheduler>
Note: If you are new to our .NET MAUI Scheduler control, please refer to its getting started documentation.
Step 4: Customize month cell template
The CellTemplate defines how each day cell in the calendar should appear. This template customizes each calendar cell to show:
- The day number which is in the top-left, with today’s date highlighted in blue using
TodayColorConverter. - A weather icon on the left side, bound using
WeatherPropertyMultiConverter. - The high and low temperatures on the right side, also retrieved via the same converter.
This layout replaces default appointments with weather visuals, making each day cell display meaningful forecast data.
MainPage.xaml
<ContentPage.Resources>
<local:WeatherPropertyMultiConverter x:Key="WeatherPropertyMultiConverter" />
<local:TodayColorConverter x:Key="TodayColorConverter" />
</ContentPage.Resources>
<!-- Cell Template for Weather Display -->
<scheduler:SchedulerMonthView.CellTemplate>
<DataTemplate x:DataType="scheduler:SchedulerMonthCellDetails">
<Grid RowDefinitions="{OnPlatform WinUI='20,Auto', MacCatalyst='20,Auto', Android='*,Auto', iOS='*,Auto'}">
<!-- Date Number (Top Left) -->
<Label Grid.Row="0"
Text="{Binding DateTime.Day}"
FontSize="16"
TextColor="{Binding DateTime, Converter={StaticResource TodayColorConverter}}"
HorizontalOptions="Start"
VerticalOptions="Start"
Margin="{OnPlatform WinUI='8,2,0,0', MacCatalyst='8,2,0,0', Android='8,8,0,0', iOS='8,2,0,0'}"
LineBreakMode="NoWrap" />
<!-- Weather Icon and Temperature Section -->
<Grid Grid.Row="1"
ColumnDefinitions="{OnPlatform WinUI='auto,*', MacCatalyst='auto,*', Android='*', iOS='*'}"
RowDefinitions="{OnPlatform WinUI='*', MacCatalyst='*', Android='auto,*', iOS='auto,*'}"
VerticalOptions="Center"
HorizontalOptions="Fill"
Margin="4,4">
<!-- Weather Icon (Left Side) -->
<Label Grid.Column="{OnPlatform WinUI=0, MacCatalyst=0, Android=0, iOS=0}"
Grid.Row="{OnPlatform WinUI=0, MacCatalyst=0, Android=0, iOS=0}"
x:Name="label"
FontSize="{OnPlatform WinUI=35, MacCatalyst=35, Android=25, iOS=25}"
HorizontalOptions="End"
VerticalOptions="Center"
Margin="4,0,0,0"
LineBreakMode="NoWrap">
<Label.Text>
<MultiBinding Converter="{StaticResource WeatherPropertyMultiConverter}"
ConverterParameter="WeatherIcon">
<Binding Path="DateTime" />
<Binding Source="{x:Reference RootPage}"
Path="BindingContext"
x:DataType="ContentPage" />
</MultiBinding>
</Label.Text>
</Label>
<!-- Temperature Section (Right Side) -->
<StackLayout Grid.Column="{OnPlatform WinUI=1, MacCatalyst=1, Android=0, iOS=0}"
Grid.Row="{OnPlatform WinUI=0, MacCatalyst=0, Android=1, iOS=1}"
Orientation="Vertical"
HorizontalOptions="Center"
VerticalOptions="Center"
Spacing="0"
Margin="0,0,4,0">
<!-- High Temperature -->
<Label FontSize="14"
HorizontalOptions="End"
HorizontalTextAlignment="End"
LineBreakMode="NoWrap">
<Label.Text>
<MultiBinding Converter="{StaticResource WeatherPropertyMultiConverter}"
ConverterParameter="HighTemp">
<Binding Path="DateTime" />
<Binding x:DataType="ContentPage"
Source="{x:Reference RootPage}"
Path="BindingContext" />
</MultiBinding>
</Label.Text>
</Label>
<!-- Low Temperature -->
<Label FontSize="14"
HorizontalOptions="End"
HorizontalTextAlignment="End"
LineBreakMode="NoWrap">
<Label.Text>
<MultiBinding Converter="{StaticResource WeatherPropertyMultiConverter}"
ConverterParameter="LowTemp">
<Binding Path="DateTime" />
<Binding Source="{x:Reference RootPage}"
Path="BindingContext"
x:DataType="ContentPage" />
</MultiBinding>
</Label.Text>
</Label>
</StackLayout>
</Grid>
</DataTemplate>
</scheduler:SchedulerMonthView.CellTemplate>
Step 5: Define the weather data interface
To make the converter reusable and decoupled from the view model, we define an interface called IWeatherProvider. This interface acts as a bridge between the converter and the view model, allowing the converter to:
- Fetch weather data for a specific date.
- Access the selected temperature unit in Fahrenheit or Celsius.
- Get the unit symbol (°F or °C) for display.
IWeatherProvider.cs
public interface IWeatherProvider
{
// Data retrieval
WeatherForecast? GetWeatherForDate(DateTime date);
// Unit info
TemperatureUnit SelectedTemperatureUnit { get; }
string TemperatureUnitSymbol { get; }
}
The view model WeatherForecastViewModel implements this interface:
WeatherForecastViewModel.cs
public class WeatherForecastViewModel : INotifyPropertyChanged, IWeatherProvider
{
public WeatherForecast? GetWeatherForDate(DateTime date)
{
return WeatherLookup.TryGetValue(date.Date, out var weather) ? weather : null;
}
public string GetTemperatureUnitSymbol()
{
return SelectedTemperatureUnit == TemperatureUnit.Fahrenheit ? "°F" : "°C";
}
public string TemperatureUnitSymbol => GetTemperatureUnitSymbol();
}
This allows the WeatherPropertyMultiConverter to work with any class that implements IWeatherProvider, making the converter flexible and clean.
Step 6: Implement value converters
TodayColorConverter is used to highlight today’s date in the calendar. It checks if a given date matches the current date:
- If it’s today, the date is shown in blue.
- Otherwise, it appears in black.
This helps users quickly identify the current day in the calendar view.
TodayColorConverter.cs
public class TodayColorConverter : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is not DateTime date)
return Colors.Black;
return date.Date == DateTime.Today ? Colors.Blue : Colors.Black;
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
WeatherPropertyMultiConverter handles the extraction and formatting of weather properties. It is used to extract and format weather details for each calendar cell.
It performs three key tasks:
- Gets the forecast for a specific date from the view model.
- Convert temperatures between Fahrenheit and Celsius if needed.
- Returns the correct value, either the weather icon, high temperature, or low temperature, based on the binding parameter.
This keeps the XAML bindings clean and ensures the UI updates correctly when the temperature unit or date changes.
WeatherPropertyMultiConverter.cs
public class WeatherPropertyMultiConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values == null || values.Length < 2)
return string.Empty;
if (values[0] is not DateTime dateTime)
return string.Empty;
if (values[1] is not IWeatherProvider provider)
return string.Empty;
var data = provider.GetWeatherForDate(dateTime);
if (data == null)
return string.Empty;
var prop = parameter as string ?? string.Empty;
var symbol = provider.TemperatureUnitSymbol;
return prop switch
{
"HighTemp" => $"{data.TemperatureHigh}{symbol}",
"LowTemp" => $"{data.TemperatureLow}{symbol}",
"WeatherIcon" => data.Icon ?? string.Empty,
_ => string.Empty
};
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
=> throw new NotSupportedException();
}
Step 7: Add a ComboBox for temperature unit switching
This SfComboBox allows users to switch between Fahrenheit and Celsius. It binds to a list of temperature units and updates the selected unit in the view model.
MainPage.xaml
xmlns:editors="clr-namespace:Syncfusion.Maui.Inputs;assembly=Syncfusion.Maui.Inputs"
<!-- Temperature Unit ComboBox -->
<editors:SfComboBox Grid.Column="1"
x:Name="temperatureUnitComboBox"
ItemsSource="{Binding TemperatureUnits}"
SelectedItem="{Binding SelectedTemperatureUnitString, Mode=TwoWay}"
IsEditable="False"
IsClearButtonVisible="False"
ShowBorder="False"
HorizontalOptions="End"
VerticalOptions="Center" >
<editors:SfComboBox.Behaviors>
<local:ForecastBehaviors/>
</editors:SfComboBox.Behaviors>
</editors:SfComboBox>
When the selection changes, a behavior (ForecastBehaviors) triggers logic to refresh the calendar view with temperatures in the chosen unit.
Note: For more details about getting started with .NET MAUI ComboBox, please refer to the official documentation.
ForecastBehaviors.cs
private void ForecastBehaviors_SelectionChanged(object? sender, Syncfusion.Maui.Inputs.SelectionChangedEventArgs e)
{
if (_comboBox != null && _comboBox.BindingContext is WeatherForecastViewModel viewModel && e.AddedItems != null && e.AddedItems.Count > 0)
{
var selectedUnit = e.AddedItems[0]?.ToString();
if (!string.IsNullOrEmpty(selectedUnit))
{
viewModel.SelectedTemperatureUnitString = selectedUnit;
//// Refresh month view
if (selectedUnit != "Fahrenheit")
{
viewModel.SelectedDate = DateTime.Now.Date;
}
else
{
viewModel.SelectedDate = viewModel.SelectedDate.AddDays(1);
}
}
}
}

GitHub reference
For more information about designing a monthly weather forecast calendar using the .NET MAUI Scheduler, refer to the GitHub demo.
Conclusion
Thank you for your time! Building a monthly weather forecast calendar using the .NET MAUI Scheduler is a great way to combine data visualization with interactive UI design. By customizing the Scheduler’s month view, binding dynamic weather data, and adding features like temperature unit switching, you can deliver a rich, user-friendly experience that feels both functional and visually appealing.
This approach is not limited to weather data; similar techniques can be applied to event calendars, resource planning, or any scenario requiring custom cell templates. With .NET MAUI’s flexibility, the possibilities are endless.
Ready to take it further? Try integrating real-time weather APIs, adding animations for weather icons, or implementing dark mode support for a polished, modern look. Your users will love the convenience and clarity this feature brings to their daily routine.
Check out our other .NET MAUI controls and demos on GitHub and share your feedback or ask questions in the comments section below.
If you’re a Syncfusion user, you can download the setup from the license and downloads page. Otherwise, you can download a free 30-day trial.
You can also contact us through our support forum, support portal, or feedback portal for queries. We are always happy to assist you!
Related Blogs
- Easily Synchronize Outlook Calendar Events in .NET MAUI Scheduler
- Easily Load Appointments in .NET MAUI Scheduler with SQLite and Perform CRUD
- Effortless Google Calendar Events Synchronization in .NET MAUI Scheduler
- Load Appointments on Demand via Web Services in .NET MAUI Scheduler Using JSON Data
This article was originally published at Syncfusion.com.
Top comments (0)