Appointments in .NET MAUI Scheduler (SfScheduler)

19 Sep 202424 minutes to read

The .NET MAUI Scheduler control has the capability to deal with appointment arrangements internally by using AppointmentsSource. In the scheduler, you can create normal, all-day appointments, spanned appointments, recurring appointments, and recurrence exception dates appointments.

The SchedulerAppointment is a class that corresponds to a specific scheduled appointment. It has some basic properties such as StartTime, EndTime, and Subject. Additional information like Notes, Location, and IsAllDay can be added.

<scheduler:SfScheduler x:Name="Scheduler" 
                       View="Week">
</scheduler:SfScheduler>
// Creating an instance for the scheduler appointment collection.
var appointment = new ObservableCollection<SchedulerAppointment>();

//Adding scheduler appointment in the scheduler appointment collection. 
appointment.Add(new SchedulerAppointment()
{
    StartTime = DateTime.Today.AddHours(9),
    EndTime = DateTime.Today.AddHours(11),
    Subject = "Client Meeting",
    Location = "Hutchison road",
});

//Adding the scheduler appointment collection to the AppointmentsSource of .NET MAUI Scheduler.
this.Scheduler.AppointmentsSource = appointment;

scheduler-appointment-in-maui-scheduler

NOTE

  • In the Scheduler, every appointment can be arranged based on its start time and duration for normal appointments in a day, week, and workweek view.
  • Whenever a timeline is viewed, the appointments (all day, span, and normal) are ordered and rendered based on the appointment start time and time duration of the appointment. This is followed by IsSpanned, IsAllDay, and normal appointments.

NOTE

View sample in GitHub

Scheduler appointment source mapping

The .NET MAUI Scheduler supports collection that implements the object interface that can be bound to populate appointments. The properties of the business object can be mapped to SchedulerAppointment by configuring the AppointmentMapping property.

Property Name Description

StartTime

This property maps the property name of a business object class to the property name of StartTime in SchedulerAppointment.

EndTime

This property maps the property name of a business object class to the property name of EndTime in SchedulerAppointment.

StartTimeZone

This property maps the property name of a business object class to the property name of StartTimeZone in SchedulerAppointment.

EndTimeZone

This property maps the property name of a business object class to the property name of EndTimeZone in SchedulerAppointment.

Subject

This property maps the property name of a business object class to the property name of Subject in SchedulerAppointment.

Id

This property maps the property name of a business object class to the property name of Id in SchedulerAppointment.

Background

This property maps the property name of a business object class to the property name of Background in SchedulerAppointment.

IsAllDay

This property maps the property name of a business object class to the property name of IsAllDay in SchedulerAppointment.

RecurrenceRule

This property maps the property name of a business object class to the property name of RecurrenceRule in SchedulerAppointment.

RecurrenceId

This property maps the property name of a business object class to the property name of RecurrenceId in SchedulerAppointment.

Notes

This property maps the property name of a business object class to the property name of Notes in SchedulerAppointment.

Location

This property maps the property name of a business object class to the property name of Location in SchedulerAppointment.

RecurrenceExceptionDates

This property maps the property name of a business object class to the property name of RecurrenceExceptionDates in SchedulerAppointment.

IsReadOnly

This property maps the property name of a business object class to the property name of IsReadOnly in SchedulerAppointment.

TextColor

This property maps the property name of a business object class to the property name of TextColor in SchedulerAppointment.

NOTE

The business object class should contain two date time fields as mandatory.

Creating business objects

Create a business object class Meeting with mandatory fields From, To, and EventName.

/// <summary>    
/// Represents the custom data properties.    
/// </summary>  
public class Meeting
{
    public DateTime From { get; set; }
    public DateTime To { get; set; }
    public bool IsAllDay { get; set; }
    public string EventName { get; set; }
    public TimeZoneInfo StartTimeZone { get; set; }
    public TimeZoneInfo EndTimeZone { get; set; }
    public Brush Background { get; set; }
    public Color TextColor { get; set; }
}

NOTE

Inherit this class from the INotifyPropertyChanged for dynamic changes in custom data.

The AppointmentMapping property of the Meeting class maps those properties to the .NET MAUI Scheduler control.

<scheduler:SfScheduler x:Name="Scheduler" 
                       View="Week" >
    <scheduler:SfScheduler.AppointmentMapping>
        <scheduler:SchedulerAppointmentMapping
                Subject="EventName"
                StartTime="From"
                EndTime="To"
                Background="Background"
                IsAllDay="IsAllDay"
                StartTimeZone="StartTimeZone"
                EndTimeZone="EndTimeZone"
                TextColorMapping="TextColor"/>
    </scheduler:SfScheduler.AppointmentMapping>
</scheduler:SfScheduler>
SfScheduler scheduler = new SfScheduler();
scheduler.View = SchedulerView.Week;
SchedulerAppointmentMapping appointmentMapping = new SchedulerAppointmentMapping();
appointmentMapping.Subject = "EventName";
appointmentMapping.StartTime = "From";
appointmentMapping.EndTime = "To";
appointmentMapping.Background = "Background";
appointmentMapping.IsAllDay = "IsAllDay";
appointmentMapping.StartTimeZone = "StartTimeZone";
appointmentMapping.EndTimeZone = "EndTimeZone";
appointmentMapping.TextColorMapping = "TextColor";
scheduler.AppointmentMapping = appointmentMapping;
this.Content = scheduler;

Create meetings of type ObservableCollection<Meeting> and assign those appointments collection to the AppointmentsSource property of the SfScheduler.

// Creating an instance for the business object class.
Meeting meeting = new Meeting();
// Setting the start time of an event.
meeting.From = DateTime.Today.Date.AddHours(9);
// Setting the end time of an event.
meeting.To = meeting.From.AddHours(2);
// Setting the subject for an event.
meeting.EventName = "Meeting";
// Setting the background color for an event.
meeting.Background = Brush.Orange;
// Setting the text color for an event.
meeting.TextColor = Colors.White;
// Creating an instance for the collection of business objects.
var Meetings = new ObservableCollection<Meeting>();
// Adding a business object to the business object Collection.
Meetings.Add(meeting);
// Adding business object in the AppointmentsSource of .NET MAUI Scheduler.
this.Scheduler.AppointmentsSource = Meetings;

business-appointment-event-in-maui-scheduler

NOTE

View sample in GitHub

Spanned appointments

The spanned appointment is the one which lasts longer than 24 hours. The spanned appointment does not block out timeslots in the Scheduler, but it will render in all-day appointment panel exclusively.

<scheduler:SfScheduler x:Name="Scheduler" 
                       View="Week" >
    <scheduler:SfScheduler.AppointmentMapping>
        <scheduler:SchedulerAppointmentMapping
                Subject="EventName"
                StartTime="From"
                EndTime="To"
                Background="Background"
                TextColorMapping="TextColor"
                IsAllDay="IsAllDay"
                StartTimeZone="StartTimeZone"
                EndTimeZone="EndTimeZone"/>
    </scheduler:SfScheduler.AppointmentMapping>
</scheduler:SfScheduler>
// Creating an instance for the business object class.
Meeting meeting = new Meeting();
// Setting the start time of an event.
meeting.From = DateTime.Today.Date.AddHours(9);
// Setting the end time of an event.
meeting.To = meeting.From.AddDays(2).AddHours(2);
// Setting the subject for an event.
meeting.EventName = "Meeting";
// Setting the background color for an event.
meeting.Background = Brush.Orange;
// Setting the text color for an event.
meeting.TextColor = Colors.Blue;
// Creating an instance for the collection of business objects.
var Meetings = new ObservableCollection<Meeting>();
// Adding a business object to the business object Collection.
Meetings.Add(meeting);
// Adding business object in the AppointmentsSource of .NET MAUI Scheduler.
this.Scheduler.AppointmentsSource = Meetings;

spanned-appointment-in-maui-scheduler

All day appointments

Appointments that are scheduled for a whole day are known as All-Day Appointments. The IsAllDay property of the SchedulerAppointment can be used to set this property. Appointments that last for a full 24 hours (exact 24 hours) will be considered as all-day appointments without setting the IsAllDay property.

<scheduler:SfScheduler x:Name="Scheduler" 
                       View="Week">
</scheduler:SfScheduler>
// Creating an instance for the scheduler appointment collection.
var appointment = new ObservableCollection<SchedulerAppointment>();

//Adding scheduler appointment in the scheduler appointment collection. 
appointment.Add(new SchedulerAppointment()
{
    StartTime = DateTime.Today.AddHours(9),
    EndTime = DateTime.Today.AddHours(10),
    Subject = "Client Meeting",
    Location = "Hutchison road",
    IsAllDay = true
});

//Adding the scheduler appointment collection to the AppointmentsSource of .NET MAUI Scheduler.
this.Scheduler.AppointmentsSource = appointment;

all-day-appointment-in-maui-scheduler

NOTE

For example: From 12/13/2021 12:00AM to 12/14/2021 12:00AM.

Read only appointment

A read-only appointment can be created with IsReadOnly property of the SchedulerAppointment.

<scheduler:SfScheduler x:Name="Scheduler" 
                       View="Week">
</scheduler:SfScheduler>
this.Scheduler.View = SchedulerView.Week;
// Creating an instance for the scheduler appointment collection.
var appointment = new ObservableCollection<SchedulerAppointment>();

//Adding scheduler appointment in the scheduler appointment collection. 
appointment.Add(new SchedulerAppointment()
{
    StartTime = DateTime.Today.AddHours(9),
    EndTime = DateTime.Today.AddHours(10),
    Subject = "Client Meeting",
    Background = Brush.Orange,
    TextColor = Colors.White,
    IsReadOnly = true,
});

//Adding the scheduler appointment collection to the AppointmentsSource of .NET MAUI Scheduler.
this.Scheduler.AppointmentsSource = appointment;

Recurrence appointment

The recurring events on a daily, weekly, monthly, or yearly basis with optimized recurrence options. The Recurring appointments can be created by setting the RecurrenceRule property in the SchedulerAppointment.

Recurrence rule

A RecurrenceRule consists of a string value (RRULE) that contains the details of the daily, weekly, monthly, or yearly recurrence appointments. Also includes the number of times it should be repeated, the duration of the interval, and the time period to be allotted for rendering an appointment.
Based on the value of the RecurrenceRule property, recurrence appointments in the SfScheduler are rendered with the respective time period.

PropertyName Purpose
FREQ Maintains the Repeat type value of the appointment. (Example: Daily, Weekly, Monthly, Yearly, Every week day) Example:FREQ=DAILY;INTERVAL=1
INTERVAL Maintains the interval value of the appointments. For example, while creating the daily appointment at an interval of 2, the appointments are rendered on the days Monday, Wednesday, and Friday. (creates the appointment on all days by leaving the interval of one day gap) Example:FREQ=DAILY;INTERVAL=1
COUNT It holds the appointment’s count value. For example, when the recurrence appointment count value is 10, it means 10 appointments are created in the recurrence series. Example: FREQ=DAILY;INTERVAL=1;COUNT=10
UNTIL This property is used to store the recurrence end date value. For example, while setting the end date of appointment as 6/30/2020, the UNTIL property holds the end date value when the recurrence actually ends. The 'T' string sets the end time value and 'Z' sets the timezone (UTC). It improves the accuracy of recurrence UNTIL property with time value. Example:FREQ=DAILY;INTERVAL=1;UNTIL=20200725T103059Z
BYDAY It holds the “DAY” values of an appointment to render. For example, create the weekly appointment, select the day(s) from the day options (Monday/Tuesday/Wednesday/Thursday/Friday/Saturday/Sunday). When Monday is selected, the first two letters of the selected day “MO” is stored in the “BYDAY” property. While selecting the multiple days, the values are separated by commas. Example:FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE;COUNT=10
BYMONTHDAY This property is used to store the date value of the Month while creating the Month recurrence appointment. * For example, while creating a Monthly recurrence appointment in the date 3, it means the BYMONTHDAY holds the value 3 and creates the appointment on 3rd day of every month. Example:FREQ=MONTHLY;BYMONTHDAY=3;INTERVAL=1;COUNT=10 * For example, while creating a Monthly recurrence appointment in the last date of every month, it means the BYMONTHDAY holds the value -1 and creates the appointment on last day of every month. Example:FREQ=MONTHLY;BYMONTHDAY=-1;INTERVAL=1;COUNT=10
BYMONTH This property is used to store the index value of the selected Month while creating the yearly appointments. For example, while creating the yearly appointment in the Month June, it means the index value for June month is 6 and it is stored in the BYMONTH field. The appointment is created on every 6th month of a year. Example:FREQ=YEARLY;BYMONTHDAY=16;BYMONTH=6;INTERVAL=1;COUNT=10
BYSETPOS This property is used to store the index value of the week. For example, while creating the monthly appointment in second week of the month, the index value of the second week (2) is stored in BYSETPOS. Example:FREQ=MONTHLY;BYDAY=MO;BYSETPOS=2;UNTIL=20200725

Creating the scheduler recurrence appointment

A recurrence rule for .NET MAUI Scheduler is used to populate the recurring appointment collection in a specific pattern. The SchedulerAppointment supports setting the RRULE directly to its RecurrenceRule property.

<scheduler:SfScheduler x:Name="Scheduler" 
                       View="Week">
</scheduler:SfScheduler>
// Creating an instance for the scheduler appointment collection.
var appointment = new ObservableCollection<SchedulerAppointment>();

//Adding scheduler appointment in the scheduler appointment collection. 
var schedulerAppointment = new SchedulerAppointment()
{
    StartTime = DateTime.Today.AddHours(9),
    EndTime = DateTime.Today.AddHours(10),
    Subject = "Occurs every alternate day",
    Id = 1,
};

//Creating a recurrence rule
schedulerAppointment.RecurrenceRule = "FREQ=DAILY;INTERVAL=2;COUNT=10";
//Adding the scheduler appointment to the scheduler appointment collection.
appointment.Add(schedulerAppointment);
//Adding the appointment collection to the AppointmentsSource of .NET MAUI Scheduler.
this.Scheduler.AppointmentsSource = appointment;

recurrence-scheduler-appointment-in-maui-scheduler

NOTE

View sample in GitHub

Creating the business object recurrence appointment

A recurrence appointment can be created in the business object class Meeting by adding mandatory fields from, to, and recurrenceRule.

/// <summary>   
/// Represents the business object data properties.   
/// </summary> 
public class Meeting
{
    public DateTime From { get; set; }
    public DateTime To { get; set; }
    public bool IsAllDay { get; set; }
    public string EventName { get; set; }
    public string Notes { get; set; }
    public TimeZoneInfo StartTimeZone { get; set; }
    public TimeZoneInfo EndTimeZone { get; set; }
    public Brush Background { get; set; }
    public object RecurrenceId { get; set; }
    public object Id { get; set; }
    public string RecurrenceRule { get; set; }
    public Color TextColor { get; set; }
}

NOTE

Inherit this class from the INotifyPropertyChanged for dynamic changes in custom data.

The AppointmentMapping property of the Meeting class maps those properties to the scheduler appointment of the .NET MAUI Scheduler control.

<scheduler:SfScheduler x:Name="Scheduler"
                       View="Week" >
    <scheduler:SfScheduler.AppointmentMapping>
        <scheduler:SchedulerAppointmentMapping
                Subject="EventName"
                StartTime="From"
                EndTime="To"
                Background="Background"
                IsAllDay="IsAllDay"
                StartTimeZone="StartTimeZone"
                EndTimeZone="EndTimeZone"
                Id="Id"      
                RecurrenceRule="RecurrenceRule"
                RecurrenceId="RecurrenceId"
                TextColorMapping="TextColor"/>
    </scheduler:SfScheduler.AppointmentMapping>
</scheduler:SfScheduler>
SfScheduler scheduler = new SfScheduler();
scheduler.View = SchedulerView.Week;

//Schedule data mapping for business objects.
SchedulerAppointmentMapping appointmentMapping = new SchedulerAppointmentMapping();
appointmentMapping.Subject = "EventName";
appointmentMapping.StartTime = "From";
appointmentMapping.EndTime = "To";
appointmentMapping.Background = "Background";
appointmentMapping.IsAllDay = "IsAllDay";
appointmentMapping.StartTimeZone = "StartTimeZone";
appointmentMapping.EndTimeZone = "EndTimeZone";
appointmentMapping.TextColorMapping = "TextColor";
scheduler.AppointmentMapping = appointmentMapping;
this.Content = scheduler;

The RecurrenceRule class of the Meeting class can be used to schedule recurring meetings for daily, weekly, monthly, or yearly intervals. Then create appointments collection Meetings of type ObservableCollection <Meeting> and assign those appointments collection Meetings to the AppointmentsSource property, which is of type object.

// Creating an instance for the business object class.
Meeting meeting = new Meeting();
// Setting the start time of an event.
meeting.From = DateTime.Today.Date.AddHours(9);
// Setting the end time of an event.
meeting.To = meeting.From.AddHours(1);
// Setting the subject for an event.
meeting.EventName = "Meeting";
// Setting the background color for an event.
meeting.Background = Brush.Orange;
// Setting the text color for an event.
meeting.TextColor = Colors.White;
//Creating a recurrence rule.
meeting.RecurrenceRule = "FREQ=DAILY;INTERVAL=2;COUNT=10";
// Setting the Id of an event.
meeting.Id = 1;
// Creating an instance for the collection of business objects.
var Meetings = new ObservableCollection<Meeting>();
// Adding a business object to the business object Collection.
Meetings.Add(meeting);
// Adding business object in the AppointmentsSource of .NET MAUI Scheduler.
this.Scheduler.AppointmentsSource = Meetings;

business-object-recurring-appointment-in-maui-scheduler

NOTE

View sample in GitHub

How to get the recurrence editor field values from RRULE?

The RRuleParser method of the .NET MAUI Scheduler retrieves the recurrence properties from the RRULE.

var dateTime = DateTime.Today.AddHours(10);
var recurrenceRule = "FREQ=DAILY;INTERVAL=1;COUNT=3";
var recurrenceProperties = SchedulerRecurrenceManager.ParseRRule(recurrenceRule, dateTime);

/// The recurrence properties retrieved from above method,
recurrenceProperties.RecurrenceType = SchedulerRecurrenceType.Daily;
recurrenceProperties.Interval = 1;
recurrenceProperties.RecurrenceCount = 3;
recurrenceProperties.RecurrenceRange = SchedulerRecurrenceRange.Count;

How to get the recurrence dates from RRULE?

The GetDateTimeOccurrences method of .NET MAUI Scheduler retrieves the occurrences date-time list from the RRULE.

var dateTime = DateTime.Today.AddHours(10);
var recurrenceRule = "FREQ=DAILY;INTERVAL=1;COUNT=3";
var dateCollection = SchedulerRecurrenceManager.GetDateTimeOccurrences(recurrenceRule, dateTime);

/// The following occurrence dates can be retrieved from the given RRULE:
var date1 = 12/14/2021 10:00:00 AM;
var date2 = 12/15/2021 10:00:00 AM;
var date3 = 12/16/2021 10:00:00 AM;

How to get the occurrence appointment from the recurring appointment?

The GetOccurrenceAppointment method of the .NET MAUI Scheduler returns the occurrence appointment for the given pattern appointment at the specified date.

var dateTime = new DateTime(2022,07,22,9,0,0);
var occurrenceAppointment = SchedulerRecurrenceManager.GetOccurrenceAppointment(Scheduler, appointment, dateTime);

How to get the recurring pattern appointment of the occurrence appointment?

The GetOccurrenceAppointment method of the .NET MAUI Scheduler returns the pattern appointment for the provided occurrence appointment.

var dateTime = new DateTime(2022,07,22,9,0,0);
var patternAppointment = SchedulerRecurrenceManager.GetPatternAppointment(Scheduler,appointment);

How to generate the RRule for the recurring appointments?

The GenerateRRule method of the .NET MAUI Scheduler generates the recurrence rule based on the given recurrence properties, the start date and end date of the recurrence appointments.

var recurrenceProperties = new SchedulerRecurrenceInfo();
recurrenceProperties.RecurrenceType = SchedulerRecurrenceType.Daily;
recurrenceProperties.Interval = 2;
recurrenceProperties.RecurrenceCount = 3;
var startTime = DateTime.Today.AddHours(9);
var endTime = DateTime.Today.AddHours(10);
var recurrenceRule = SchedulerRecurrenceManager.GenerateRRule(recurrenceProperties, startTime, endTime);

Recurrence pattern exceptions

The Recurrence pattern appointments can be deleted or changed by handling exception dates and exception appointments.

Recurrence exception dates

By adding exception dates to the recurring appointment, any occurrence appointment can be removed that is an exception from the recurrence pattern.

Recurrence exception appointment

Any appointment that differs from the recurrence pattern can be changed by adding this appointment in the AppointmentsSource of the .NET MAUI Scheduler.

Creating the recurrence exceptions for scheduler appointment

The Recurrence exception appointments and recurrence exception dates can be added to SchedulerAppointment or removed by using its RecurrenceExceptionDates property.

Delete occurrence from recurrence pattern appointment or adding exception dates to recurrence pattern for scheduler appointment

An occurrence of the recurrence pattern appointment which is an exception can be deleted by using the RecurrenceExceptionDates property of SchedulerAppointment. The deleted occurrence date will be considered as recurrence exception date.

<scheduler:SfScheduler x:Name="Scheduler" 
                       View="Week">
</scheduler:SfScheduler>
// Creating an instance for the scheduler appointment collection.
var appointment = new ObservableCollection<SchedulerAppointment>();

//Adding Recurrence and exception appointment in the scheduler appointment collection. 
var schedulerAppointment = new SchedulerAppointment()
{
    Id = 1,
    StartTime = DateTime.Today.AddHours(9),
    EndTime = DateTime.Today.AddHours(10),
    Subject = "Daily scrum meeting",
    RecurrenceRule = "FREQ=DAILY;INTERVAL=1;COUNT=10"
};

//Add the exceptionDates to avoid occurrence on specific dates.
DateTime exceptionDate = schedulerAppointment.StartTime.AddDays(3).Date;
schedulerAppointment.RecurrenceExceptionDates = new ObservableCollection<DateTime>()
{
    exceptionDate,
};

//Adding the scheduler appointment to the scheduler appointment collection.
appointment.Add(schedulerAppointment);

//Adding the scheduler appointment collection to the AppointmentsSource of .NET MAUI Scheduler.
this.Scheduler.AppointmentsSource = appointment;

adding-exception-dates-to-recurrence-pattern-scheduler-appointment-in-maui-scheduler

NOTE

View sample in GitHub

Add exception appointment to the recurrence pattern for scheduler appointment

Also add an exception appointment which is changed or modified occurrence of the recurrence pattern appointment to the AppointmentsSource of SfScheduler. To add a changed occurrence, ensure to set the RecurrenceId of that occurrence and add the date of that occurrence to the RecurrenceExceptionDates of recurrence pattern appointment. The RecurrenceId of changed occurrence should hold the exact recurrence pattern appointment Id.

<scheduler:SfScheduler x:Name="Scheduler" 
                       View="Week">
</scheduler:SfScheduler>
// Creating an instance for the scheduler appointment collection.
var appointment = new ObservableCollection<SchedulerAppointment>();

//Adding Recurrence and exception appointment in the scheduler appointment collection. 
var schedulerAppointment = new SchedulerAppointment()
{
    Id = 1,
    StartTime = DateTime.Today.AddHours(9),
    EndTime = DateTime.Today.AddHours(10),
    Subject = "Daily scrum meeting",
    RecurrenceRule = "FREQ=DAILY;INTERVAL=1;COUNT=10"
};

//Add the exceptionDates to avoid occurrence on specific dates.
DateTime changedExceptionDate = schedulerAppointment.StartTime.AddDays(3).Date;
schedulerAppointment.RecurrenceExceptionDates = new ObservableCollection<DateTime>()
{
    changedExceptionDate,
};

//Adding the scheduler appointment to the scheduler appointment collection.
appointment.Add(schedulerAppointment);

// Creating an exception occurrence appointment by changing the start time or end time. 
// RecurrenceId is set to 1, so it will be the changed occurrence for the above-created pattern appointment. 
var exceptionAppointment = new SchedulerAppointment()
{
    Id = 2,
    Subject = "Scrum meeting - Changed Occurrence",
    StartTime = new DateTime(changedExceptionDate.Year, changedExceptionDate.Month, changedExceptionDate.Day, 11, 0, 0),
    EndTime = new DateTime(changedExceptionDate.Year, changedExceptionDate.Month, changedExceptionDate.Day, 12, 0, 0),
    Background = Brush.DeepPink,
    TextColor = Colors.White,
    RecurrenceId = 1
};

//Adding the exception occurrence appointment to the scheduler appointment collection.
appointment.Add(exceptionAppointment);

//Adding the scheduler appointment collection to the AppointmentsSource of .NET MAUI Scheduler.
this.Scheduler.AppointmentsSource = appointment;

adding-exception-to-the-recurrence-pattern-scheduler-appointment-in-maui-scheduler

NOTE

  • The RecurrenceId of an exception appointment and the Id of its pattern appointment should have the same value.
  • The Exception recurrence appointment does not have the RecurrenceRule, so for an exception appointment, it will be reset to empty.
  • The exception appointment should have a different Id with original pattern appointment Id.
  • The exception appointment should be a normal appointment and should not be created as a recurring appointment, since its occurrence is from a recurrence pattern.
  • The RecurrenceExceptionDates should be in a Universal Time Coordinates (UTC) time zone.

NOTE

View sample in GitHub

Create the recurrence exceptions for business object

The recurrence exception appointments and recurrence exception dates can be added to business object or removed them from business object, a business object class Meeting can be created with mandatory fields RecurrenceExceptionDates and RecurrenceId.

Delete occurrence from the recurrence pattern appointment or adding exception dates to recurrence pattern for business object

An occurrence of the recurrence pattern appointment which is an exception can be deleted by using the RecurrenceExceptionDates property of AppointmentMapping class which is used to map the exception dates to the scheduler recurrence appointment. The deleted occurrence date will be considered as a recurrence exception date.
To add the exception dates in the recurrence series of business object, add the RecurrenceExceptionDates, EventName, From, To, Color, RecurrenceRule properties to the business object class Meeting.

/// <summary>    
/// Represents the custom data properties.    
/// </summary>    
public class Meeting
{
    public ObservableCollection<DateTime> RecurrenceExceptions { get; set; }
    public DateTime From { get; set; }
    public DateTime To { get; set; }
    public bool IsAllDay { get; set; }
    public string EventName { get; set; }
    public string Notes { get; set; }
    public TimeZoneInfo StartTimeZone { get; set; }
    public TimeZoneInfo EndTimeZone { get; set; }
    public Brush Background { get; set; }
    public Color TextColor { get; set; }
    public object RecurrenceId { get; set; }
    public object Id { get; set; }
    public string RecurrenceRule { get; set; }
}

NOTE

Inherit this class from the INotifyPropertyChanged for dynamic changes in custom data.

The property RecurrenceExceptionDates should map with the business object class of AppointmentMapping class to map the exception dates to the scheduled appointment.

<scheduler:SfScheduler x:Name="Scheduler" 
                       View="Week" >
    <scheduler:SfScheduler.AppointmentMapping>
        <scheduler:SchedulerAppointmentMapping
                Subject="EventName"
                StartTime="From"
                EndTime="To"
                Background="Background"
                IsAllDay="IsAllDay"
                StartTimeZone="StartTimeZone"
                EndTimeZone="EndTimeZone"
                Id="Id"        
                RecurrenceExceptionDates="RecurrenceExceptions"
                RecurrenceRule="RecurrenceRule"
                RecurrenceId="RecurrenceId"
                TextColorMapping="TextColor"/>
    </scheduler:SfScheduler.AppointmentMapping>
</scheduler:SfScheduler>
// Creating an instance for the business object class.
Meeting recurrenceAppointment = new Meeting();
// Setting the start time of an event.
recurrenceAppointment.From = DateTime.Today.Date.AddHours(9);
// Setting the end time of an event.
recurrenceAppointment.To = recurrenceAppointment.From.AddHours(1);
// Setting the subject for an event.
recurrenceAppointment.EventName = "Occurs Daily";
// Setting the background color for an event.
recurrenceAppointment.Background = Brush.Orange;
// Setting the text color for an event.
meeting.TextColor = Colors.White;
//Creating a recurrence rule.
recurrenceAppointment.RecurrenceRule = "FREQ=DAILY;COUNT=20";
// Setting the Id of an event.
recurrenceAppointment.Id = 1;
// Add the exceptionDates to avoid occurrence on specific dates.
DateTime exceptionDate = recurrenceAppointment.From.AddDays(3).Date;
// Add RecurrenceExceptionDates to appointment.
recurrenceAppointment.RecurrenceExceptions = new ObservableCollection<DateTime>()
{
    exceptionDate
};
// Creating an instance for the collection of business objects.
var Meetings = new ObservableCollection<Meeting>();
// Adding a business object to the business object Collection.
Meetings.Add(recurrenceAppointment);
// Adding business object in the AppointmentsSource of .NET MAUI Scheduler.
this.Scheduler.AppointmentsSource = Meetings;

adding-exception-dates-to-recurrence-pattern-custom-appointment-in-maui-scheduler

NOTE

Exception dates should be Universal Time Coordinates (UTC) time zone.

NOTE

View sample in GitHub

Add an exception appointment to the recurrence pattern for business object

Also add an exception appointment which is changed or modified occurrence of the recurrence pattern appointment to the AppointmentsSource of SfScheduler. To add the changed occurrence, ensure to set the RecurrenceId of that occurrence and add the date of that occurrence to RecurrenceExceptionDates of recurrence pattern appointment. The RecurrenceId of changed occurrence should hold the exact recurrence pattern appointment Id. Map the equivalent properties of Id, RecurrenceId, and RecurrenceExceptionDates properties from the business object to the Id and RecurrenceExceptionDates properties of AppointmentMapping.

Add the created exception recurrence appointment to the SfScheduler AppointmentsSource.

<scheduler:SfScheduler x:Name="Scheduler" 
                       View="Week" >
    <scheduler:SfScheduler.AppointmentMapping>
        <scheduler:SchedulerAppointmentMapping
                Subject="EventName"
                StartTime="From"
                EndTime="To"
                Background="Background"
                TextColorMapping="TextColor"
                IsAllDay="IsAllDay"
                StartTimeZone="StartTimeZone"
                EndTimeZone="EndTimeZone"
                Id="Id"        
                RecurrenceExceptionDates="RecurrenceExceptions"
                RecurrenceRule="RecurrenceRule"
                RecurrenceId="RecurrenceId"/>
    </scheduler:SfScheduler.AppointmentMapping>
</scheduler:SfScheduler>
var recursiveAppointmentCollection = new ObservableCollection<Meeting>();
//Adding business object in the business object collection. 
Meeting dailyEvent = new Meeting
{
    EventName = "Daily scrum meeting",
    From = DateTime.Today.Date.AddHours(9),
    To = DateTime.Today.Date.AddHours(10),
    Background = Brush.Orange,
    TextColor = Colors.White,
    RecurrenceRule = "FREQ=DAILY;INTERVAL=1;COUNT=10",
    Id = 1
};

//Adding business object in the business object collection.
recursiveAppointmentCollection.Add(dailyEvent);

//Add ExceptionDates to avoid occurrence on specific dates.
DateTime changedExceptionDate = dailyEvent.From.AddDays(3).Date;
dailyEvent.RecurrenceExceptions = new ObservableCollection<DateTime>()
{
    changedExceptionDate
};
//Change start time or end time of an occurrence.
Meeting changedEvent = new Meeting
{
    EventName = "Scrum meeting - Changed Occurrence",
    From = new DateTime(changedExceptionDate.Year, changedExceptionDate.Month, changedExceptionDate.Day, 13, 0, 0),
    To = new DateTime(changedExceptionDate.Year, changedExceptionDate.Month, changedExceptionDate.Day, 14, 0, 0),
    Background = Brush.DeepPink,
    TextColor = Colors.White,
    RecurrenceRule = "FREQ=DAILY;INTERVAL=1;COUNT=10",
    Id = 2,
    RecurrenceId = 1
};

recursiveAppointmentCollection.Add(changedEvent);
// Adding business object in the AppointmentsSource of .NET MAUI Scheduler.
this.Scheduler.AppointmentsSource = recursiveAppointmentCollection;

NOTE

  • The RecurrenceId of exception appointment and the Id of its pattern appointment should have same value.
  • The Exception recurrence appointment does not have the RecurrenceRule, so for an exception appointment, it will be reset to empty.
  • The exception appointment should have different Id with original pattern appointment Id.
  • The exception appointment should be a normal appointment and should not be created as recurring appointment, since its occurrence from the recurrence pattern.
  • The recurrenceExceptions should be in a Universal Time Coordinates (UTC) time zone.

NOTE

View sample in GitHub

Suspend and resume the appointment UI rendering

Schedule allows you to suspend and resume the appointment UI update while performing collection changes (Add/Remove/Reset) to improve UI rendering when working with large appointment collections. SuspendAppointmentViewUpdate method will suspend appointment UI rendering until you resume it when large number of data added dynamically in schedule AppointmentsSource to avoid each time updating UI when collection changes. After data added dynamically in schedule, you can call ResumeAppointmentViewUpdate to update the appointment UI rendering.

// Creating an instance for the scheduler appointment collection.
var appointment = new ObservableCollection<SchedulerAppointment>();
 
//Adding scheduler appointment in the scheduler appointment collection. 
appointment.Add(new SchedulerAppointment()
{
    StartTime = DateTime.Today.AddHours(9),
    EndTime = DateTime.Today.AddHours(11),
    Subject = "Client Meeting",
    Location = "Hutchison road",
});
 
//Adding the scheduler appointment collection to the AppointmentsSource of .NET MAUI Scheduler.
this.Scheduler.AppointmentsSource = appointment;
 
this.Scheduler.ViewChanged += Scheduler_ViewChanged;
 
 
private void Scheduler_ViewChanged(object? sender, SchedulerViewChangedEventArgs e)
{
    // Suspends the Appointment Update.
    this.Scheduler.SuspendAppointmentViewUpdate();
 
    for (int i = 0; i < e.NewVisibleDates.Count; i++)
    {
        var visibleDate = e.NewVisibleDates[i].Date;
        var scheduleAppointment = new SchedulerAppointment()
        {
            StartTime = visibleDate.AddHours(10),
            EndTime = visibleDate.AddHours(12),
            Subject = visibleDate.ToString("dd/MM/yyyy"),
            Background = Colors.Red,
        };
        appointment.Add(scheduleAppointment);
    }
 
    // Resumes the Appointment Update.
    this.Scheduler.ResumeAppointmentViewUpdate();
}

Appointment appearance customization

The appointment appearance customization can be achieved by using the TextStyle and AppointmentTemplate properties in the SfScheduler.

Customize appointment appearance using text style

The appointment text style can be customized by using the AppointmentTextStyle property of the SfScheduler.

<scheduler:SfScheduler x:Name="Scheduler" 
                       View="Week">
</scheduler:SfScheduler>
var appointments = new ObservableCollection<SchedulerAppointment>();
appointments.Add(new SchedulerAppointment()
{
    Subject = "meeting",
    StartTime = DateTime.Now,
    EndTime = DateTime.Now.AddHours(1),
});
this.Scheduler.AppointmentsSource = appointments;
var appointmentTextStyle = new SchedulerTextStyle()
{
    TextColor = Colors.Red,
    FontSize = 12,
};
this.Scheduler.AppointmentTextStyle = appointmentTextStyle;

customize-appointment-text-style-appearence-in-maui-scheduler

Customize appointment appearance using DataTemplate

You can customize the appointment appearance by using the AppointmentTemplate properties of DaysView, TimelineView, and MonthView in the SfScheduler.

<Grid>
    <Grid.Resources>
        <DataTemplate x:Key="appointmentTemplate">
            <Grid Background="MediumPurple">
                <Label Text="{Binding Subject}" TextColor="White" HorizontalOptions="Center" VerticalOptions="Center" FontFamily="Bold"/>
            </Grid>
        </DataTemplate>
    </Grid.Resources>
    <scheduler:SfScheduler  x:Name="Scheduler" 
                            View="Day"
                            AllowedViews="Day,Week,WorkWeek,Month,Agenda,TimelineDay,TimelineWeek,TimelineWorkWeek,TimelineMonth">
        <scheduler:SfScheduler.DaysView>
            <scheduler:SchedulerDaysView AppointmentTemplate="{StaticResource appointmentTemplate}"/>
        </scheduler:SfScheduler.DaysView>
        <scheduler:SfScheduler.TimelineView>
            <scheduler:SchedulerTimelineView AppointmentTemplate="{StaticResource appointmentTemplate}"/>
        </scheduler:SfScheduler.TimelineView>
        <scheduler:SfScheduler.MonthView>
            <scheduler:SchedulerMonthView AppointmentTemplate="{StaticResource appointmentTemplate}"/>
        </scheduler:SfScheduler.MonthView>
    </scheduler:SfScheduler>
 </Grid>
this.Scheduler.AllowedViews = SchedulerViews.Day | SchedulerViews.Week | SchedulerViews.WorkWeek | SchedulerViews.Month | SchedulerViews.Agenda | SchedulerViews.TimelineDay | SchedulerViews.TimelineWeek | SchedulerViews.TimelineWorkWeek | SchedulerViews.TimelineMonth;
var appointments = new ObservableCollection<SchedulerAppointment>();
appointments.Add(new SchedulerAppointment()
{
    Subject = "meeting",
    StartTime = DateTime.Now,
    EndTime = DateTime.Now.AddHours(1),
});
this.Scheduler.AppointmentsSource = appointments;

customize-appointment-template-appearance-in-maui-scheduler

NOTE

  • By default, the SchedulerAppointment is set as the BindingContext for AppointmentTemplate for both SchedulerAppointment and custom data object in AppointmentsSource.
  • The Custom data object can be bound in AppointmentTemplate by using SchedulerAppointment.DataItem.

Customize appointment appearance using DataTemplateSelector

You can customize the appointment appearance by using the AppointmentTemplate property of DaysView, TimelineView, and MonthView in the SfScheduler. The DataTemplateSelector can choose a DataTemplate at runtime based on the value of a data-bound to scheduler appointment appearance by using the AppointmentTemplate. It allows you to choose a different data template for each appointment, as well as to customize the appearance of a particular appointment based on certain conditions.

<Grid>
    <Grid.Resources>
        <DataTemplate x:Key="normalDateTemplate">
            <Grid Background="LightGreen">
                <Label x:Name="label" HorizontalOptions="Center"  VerticalOptions="Center" TextColor="Black" FontSize="12"  Text="{Binding Subject}" />
            </Grid>
        </DataTemplate>
        <DataTemplate x:Key="todayDateTemplate">
            <Grid Background="MediumPurple">
                <Label x:Name="label" HorizontalOptions="Center" VerticalOptions="Center" TextColor="White" FontSize="12"  Text="{Binding Subject}" />
            </Grid>
        </DataTemplate>
        <local:AppointmentTemplateSelector x:Key="appointmentTemplateSelector" TodayDateTemplate="{StaticResource todayDateTemplate}" NormalDateTemplate="{StaticResource normalDateTemplate}"/>
    </Grid.Resources>
    <scheduler:SfScheduler x:Name="Scheduler" 
                           View="Week" >
        <scheduler:SfScheduler.DaysView>
            <scheduler:SchedulerDaysView AppointmentTemplate="{StaticResource appointmentTemplateSelector}" />
        </scheduler:SfScheduler.DaysView>
        <scheduler:SfScheduler.TimelineView>
            <scheduler:SchedulerTimelineView AppointmentTemplate="{StaticResource appointmentTemplateSelector}" />
        </scheduler:SfScheduler.TimelineView>
        <scheduler:SfScheduler.MonthView>
            <scheduler:SchedulerMonthView AppointmentTemplate="{StaticResource appointmentTemplateSelector}" />
        </scheduler:SfScheduler.MonthView>
    </scheduler:SfScheduler>
 </Grid>
public class AppointmentTemplateSelector : DataTemplateSelector
{
    public AppointmentTemplateSelector()
    {
    }
    public DataTemplate NormalDateTemplate { get; set; }
    public DataTemplate TodayDateTemplate { get; set; }
    protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
    {
        var schedulerAppointment = item as SchedulerAppointment;
        if (schedulerAppointment.ActualStartTime.Date == DateTime.Today.Date)
            return TodayDateTemplate;
        else
            return NormalDateTemplate;
    }
}
this.Scheduler.View = SchedulerView.Week;
var appointments = new ObservableCollection<SchedulerAppointment>();
appointments.Add(new SchedulerAppointment()
{
    Subject = "Meeting",
    StartTime = DateTime.Today.Date.AddHours(9),
    EndTime = DateTime.Today.Date.AddHours(10),
});
appointments.Add(new SchedulerAppointment()
{
    Subject = "Project plan",
    StartTime = DateTime.Today.Date.AddDays(1).AddHours(10),
    EndTime = DateTime.Today.Date.AddDays(1).AddHours(11),
});
this.Scheduler.AppointmentsSource = appointments;

NOTE

  • The BindingContext for AppointmentTemplate for both SchedulerAppointment and SchedulerAppointment.DataItem in AppointmentsSource.
  • When using data template selector, performance issues occur as the conversion template views take time within the framework.

Appointment selection background

The selection view of appointment can be customized by using the SelectedAppointmentBackground property in the SfScheduler.

<scheduler:SfScheduler x:Name="Scheduler" 
                       SelectedAppointmentBackground="Orange">
</scheduler:SfScheduler>
this.Scheduler.SelectedAppointmentBackground = Brush.Orange;

appointment-selection-background-in-maui-scheduler

NOTE