Load On Demand in WinUI Scheduler (SfScheduler)
19 Apr 202216 minutes to read
The scheduler supports loading appointments on-demand with loading indicator and it improves the loading performance when there is appointments range for multiple years.
QueryAppointments event
The QueryAppointments event is used to load appointments on-demand for the visible date range. Start and stop the loading indicator animation before and after the appointments loaded using the ShowBusyIndicator.
The QueryAppointmentsEventArgs has the following members which provide information for the QueryAppointments
event.
VisibleDateRange: Gets the current visible date range of scheduler that is used to load the appointments.
<scheduler:SfScheduler x:Name="Schedule"
ViewType="Month"
QueryAppointments="Schedule_QueryAppointments" >
</scheduler:SfScheduler>
this.Schedule.QueryAppointments += Schedule_QueryAppointments;
/// <summary>
/// current day meetings
/// </summary>
private List<string> currentDayMeetings;
/// <summary>
/// color collection
/// </summary>
private List<Brush> colorCollection;
private void Schedule_QueryAppointments(object sender, QueryAppointmentsEventArgs e)
{
this.Schedule.ShowBusyIndicator = true;
this.InitializeDataForBookings();
this.Schedule.ItemsSource = this.GenerateSchedulerAppointments(e.VisibleDateRange);
this.Schedule.ShowBusyIndicator = false;
}
private void InitializeDataForBookings()
{
this.currentDayMeetings = new List<string>();
this.currentDayMeetings.Add("General Meeting");
this.currentDayMeetings.Add("Plan Execution");
this.currentDayMeetings.Add("Project Plan");
this.currentDayMeetings.Add("Consulting");
this.currentDayMeetings.Add("Performance Check");
this.currentDayMeetings.Add("Yoga Therapy");
this.currentDayMeetings.Add("Plan Execution");
this.currentDayMeetings.Add("Project Plan");
this.currentDayMeetings.Add("Consulting");
this.currentDayMeetings.Add("Performance Check");
this.colorCollection = new List<Brush>();
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 133, 81, 242)));
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 140, 245, 219)));
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 83, 99, 250)));
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 255, 222, 133)));
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 45, 153, 255)));
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 253, 183, 165)));
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 198, 237, 115)));
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 253, 185, 222)));
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 83, 99, 250)));
}
/// <summary>
/// Method to generate the schedule appointments.
/// </summary>
/// <param name="dateRange"></param>
/// <returns></returns>
private IEnumerable GenerateSchedulerAppointments(DateRange dateRange)
{
Random ran = new Random();
int daysCount = (dateRange.ActualEndDate - dateRange.ActualStartDate).Days;
var appointments = new ScheduleAppointmentCollection();
for (int i = 0; i < 50; i++)
{
var startTime = dateRange.ActualStartDate.AddDays(ran.Next(0, daysCount + 1)).AddHours(ran.Next(0, 24));
appointments.Add(new ScheduleAppointment
{
StartTime = startTime,
EndTime = startTime.AddHours(1),
Subject = currentDayMeetings[ran.Next(0, currentDayMeetings.Count)],
AppointmentBackground = colorCollection[ran.Next(0, colorCollection.Count)],
});
}
return appointments;
}
The QueryAppointments will be raised if any one of the following action is taken.
Once the ViewChanged event is raised, the QueryAppointments
will be raised.
If the appointment has been added, removed, or changed (Resize, drag, and drop) in the current time visible date range, then the QueryAppointments
event will not be triggered. Since the appointments for that visible date range have been loaded already.
The QueryAppointments
event is triggered when the Schedule ResourceCollection is updated to load appointments based on the changed resource collection.
The QueryAppointments
event will be triggered when the ResourceGroupType is changed.
Load On Demand command
The Scheduler notifies the LoadOnDemandCommand when the user changes the visible date range. Get a visible date range from the QueryAppointmentsEventArgs. The default value for this ICommand
is null. The QueryAppointmentsEventArgs
passed as a command parameter.
Define a ViewModel class that implements command and handle it by the CanExecute
and Execute
methods to check and execute on-demand loading. In execute method, perform the following operations.
- Start and stop the loading indicator animation before and after the appointments loaded using the ShowBusyIndicator.
- Once the appointment collection is got, load into the scheduler
ItemsSource.
<scheduler:SfScheduler x:Name="Schedule"
ViewType="Month"
ShowBusyIndicator="{Binding ShowBusyIndicator}"
LoadOnDemandCommand="{Binding LoadOnDemandCommand}"
ItemsSource="{Binding Events}">
<scheduler:SfScheduler.DataContext>
<local:LoadOnDemandViewModel />
</scheduler:SfScheduler.DataContext>
</scheduler:SfScheduler>
public class LoadOnDemandViewModel : NotificationObject
{
public DelegateCommand LoadOnDemandCommand { get; set; }
private IEnumerable events;
public IEnumerable Events
{
get { return events; }
set
{
events = value;
this.RaisePropertyChanged("Events");
}
}
private bool showBusyIndicator;
public bool ShowBusyIndicator
{
get { return showBusyIndicator; }
set
{
showBusyIndicator = value;
this.RaisePropertyChanged("ShowBusyIndicator");
}
}
public LoadOnDemandViewModel()
{
this.InitializeDataForBookings();
this.LoadOnDemandCommand = new DelegateCommand(ExecuteOnDemandLoading, CanExecuteOnDemandLoading);
}
public event PropertyChangedEventHandler PropertyChanged;
public async void ExecuteOnDemandLoading(object parameter)
{
this.ShowBusyIndicator = true;
await Task.Delay(1000);
Application.Current.Resources.DispatcherQueue.TryEnqueue(() =>
{
this.Events = this.GenerateSchedulerAppointments((parameter as QueryAppointmentsEventArgs).VisibleDateRange);
});
this.ShowBusyIndicator = false;
}
private bool CanExecuteOnDemandLoading(object sender)
{
return true;
}
/// <summary>
/// current day meetings
/// </summary>
private List<string> currentDayMeetings;
/// <summary>
/// color collection
/// </summary>
private List<Brush> colorCollection;
private void InitializeDataForBookings()
{
this.currentDayMeetings = new List<string>();
this.currentDayMeetings.Add("General Meeting");
this.currentDayMeetings.Add("Plan Execution");
this.currentDayMeetings.Add("Project Plan");
this.currentDayMeetings.Add("Consulting");
this.currentDayMeetings.Add("Performance Check");
this.currentDayMeetings.Add("Yoga Therapy");
this.currentDayMeetings.Add("Plan Execution");
this.currentDayMeetings.Add("Project Plan");
this.currentDayMeetings.Add("Consulting");
this.currentDayMeetings.Add("Performance Check");
this.colorCollection = new List<Brush>();
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 133, 81, 242)));
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 140, 245, 219)));
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 83, 99, 250)));
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 255, 222, 133)));
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 45, 153, 255)));
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 253, 183, 165)));
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 198, 237, 115)));
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 253, 185, 222)));
this.colorCollection.Add(new SolidColorBrush(Color.FromArgb(255, 83, 99, 250)));
}
private IEnumerable GenerateSchedulerAppointments(DateRange dateRange)
{
Random ran = new Random();
int daysCount = (dateRange.ActualEndDate - dateRange.ActualStartDate).Days;
var appointments = new ScheduleAppointmentCollection();
for (int i = 0; i < 50; i++)
{
var startTime = dateRange.ActualStartDate.AddDays(ran.Next(0, daysCount + 1)).AddHours(ran.Next(0, 24)); appointments.Add(new ScheduleAppointment
{
StartTime = startTime,
EndTime = startTime.AddHours(1),
Subject = currentDayMeetings[ran.Next(0, currentDayMeetings.Count)],
AppointmentBackground = colorCollection[ran.Next(0, colorCollection.Count)],
});
}
return appointments;
}
}
The LoadOnDemandCommand will be invoked if any one of the following actions are taken.
-
Once the ViewChanged event is raised, the
LoadOnDemandCommand
will also be raised. -
If the appointment has been added, removed, or changed (Resize, drag, and drop) in the current time visible date range, then the
LoadOnDemandCommand
will not be triggered. Since the appointments for that visible date range have been loaded already. -
The
LoadOnDemandCommand
is triggered when the ScheduleResourceCollection
is updated to load the appointments based on the changed resource collection. -
The
LoadOnDemandCommand
will be triggered when theResourceGroupType
is changed.
Load On Demand for recurring appointment
The scheduler will add the occurrences of recurrence series based on the visible date range, use the RecurrenceHelper.GetRecurrenceDateTimeCollection to compare and load the recurrence appointment on-demand in the ItemsSource.
The recurrence appointment should be added to the Scheduler ItemsSource
until the date of recurrence ends.
If RecurrenceRule added with count or end date, use the RecurrenceHelper.GetRecurrenceDateTimeCollection method to get the recurrence date collection and compare recursive dates in the current visible date range. Then, add the recurrence appointment in the scheduler ItemsSource. If the recursive dates are in the current visible date range.
If the RecurrenceRule
is added without an end date, then the recurrence appointment should be added in the scheduler ItemsSource
when all the visible dates changed from the recurrence start date.
NOTE
Show busy indicator
The Scheduler
supports showing the busy indicator by using the ShowBusyIndicator property. The default value is set to false.
If the value is set to true
then the busy indicator will be load on view or the visible date changed.
<scheduler:SfScheduler x:Name="Schedule"
ShowBusyIndicator="True">
</scheduler:SfScheduler>
this.Schedule.ShowBusyIndicator = true;