Articles in this section

How to load appointments on demand in the MAUI Scheduler (SfScheduler)?

The .NET MAUI Scheduler allows you to load appointments dynamically based on the visible date range, enhancing performance by only loading the required data. This can be achieved using the QueryAppointmentsCommand to load appointments as the scheduler's visible date range changes. This guide demonstrates how to implement this functionality.

Note:

The QueryAppointments event or command will be triggered if any one of the following actions is performed.,

  • Once the ViewChanged event is triggered, the QueryAppointments will be triggered.
  • If an appointment has been added or removed on the currently visible dates, then the QueryAppointments event will not be triggered because the appointments for that visible date are already loaded.
  • In the scheduler agenda view, the QueryAppointments event is used to load more appointments when the new month is loaded on view, whereas the new month appointments are added in scheduler AppointmentsSource.
  • Other than the agenda view, the scheduler AppointmentsSource can be reset for a new visible date range to improve appointment loading performance.

 

Declare the ICommand to bind the QueryAppointmentsCommand and on command execute to load the appointments based on the visible date range. You can also show the busy indicator by using the ShowBusyIndicator property to show the loading indicator when appointments are loaded dynamically, and you need to start and stop the loading indicator animation before and after the appointments are loaded. 

C#

Create a LoadOnDemandViewModel implementing INotifyPropertyChanged to manage appointment loading based on the visible date range.

public class LoadOnDemandViewModel : INotifyPropertyChanged
{
    private bool showBusyIndicator;
    private ObservableCollection<SchedulerAppointment>? events;
    
     /// <summary>
    /// Gets or sets the value to appointments load dynalically.
    /// </summary>
 
    public ICommand QueryAppointmentsCommand { get; set; }
 
    /// <summary>
    /// Gets or sets the value to display the scheduler view.
    /// </summary>
 
    public SchedulerView SchedulerView { get; set; }
 
    /// <summary>
    /// Gets or sets the value to display appointment collection.
    /// </summary>
 
    public ObservableCollection<SchedulerAppointment>? Events
    {
        get { return events; }
        set
        {
            events = value;
            this.RaiseOnPropertyChanged(nameof(Events));
        }
    }
   
    /// <summary>
    /// Gets or sets the value to stop the indicator after appointments loading.
    /// </summary>
 
    public bool ShowBusyIndicator
    {
        get { return showBusyIndicator; }
        set
        {
            showBusyIndicator = value;
            this.RaiseOnPropertyChanged(nameof(ShowBusyIndicator));
        }
    }
 
    public event PropertyChangedEventHandler? PropertyChanged;
 
    public LoadOnDemandViewModel()
    {
        this.SchedulerView = SchedulerView.Week;
 
        //// QueryAppointmentsCommand used to load the appointments dynamically based on the visible date range. 
        this.QueryAppointmentsCommand = new Command<object>(LoadMoreAppointments, CanLoadMoreAppointments);
    }
 
    private void RaiseOnPropertyChanged(string propertyName)
    {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
 
    private bool CanLoadMoreAppointments(object obj)
    {
        return true;
    }
 
    private async void LoadMoreAppointments(object obj)
    {
        //// ShowBusyIndicator is used to start and stop the loading indicator animation before and after appointments are loaded with specified delay.
 
        //// You need to stop the loading indicator once appointments added.
        this.ShowBusyIndicator = true;
 
        //// Delay set to load the appointments and busy indicator.
        await Task.Delay(1500);
 
        var eventCollection = this.GenerateSchedulerAppointments(((SchedulerQueryAppointmentsEventArgs)obj).VisibleDates);
 
        //// Other than agenda view the appointment collection reset with current visible date range.
        if (this.SchedulerView != SchedulerView.Agenda)
        {
            this.Events = eventCollection;
        }
 
        //// For scheduler agenda view the new visible date range appointments added in collection.
 
        else
        {
            foreach (var meeting in eventCollection)
            {
                this.Events?.Add(meeting);
            }
        }
 
      //// You need to stop the loading indicator once appointments added.
        this.ShowBusyIndicator = false;
    }
 
    private ObservableCollection<SchedulerAppointment> GenerateSchedulerAppointments(List<DateTime> visibleDates)
    {
        var brush = new ObservableCollection<Brush>
{
    new SolidColorBrush(Color.FromArgb("#FF8B1FA9")),
    new SolidColorBrush(Color.FromArgb("#FFD20100")),
    new SolidColorBrush(Color.FromArgb("#FFFC571D")),
    new SolidColorBrush(Color.FromArgb("#FF36B37B")),
    new SolidColorBrush(Color.FromArgb("#FF3D4FB5")),
    new SolidColorBrush(Color.FromArgb("#FFE47C73")),
    new SolidColorBrush(Color.FromArgb("#FF636363")),
    new SolidColorBrush(Color.FromArgb("#FF85461E")),
    new SolidColorBrush(Color.FromArgb("#FF0F8644")),
    new SolidColorBrush(Color.FromArgb("#FF01A1EF"))
};
 
        var subjects = new ObservableCollection<string>
{
    "Business Meeting",
    "Conference",
    "Medical check up",
    "Performance Check",
    "Consulting",
    "Project Status Discussion",
    "Client Meeting",
    "General Meeting",
    "Yoga Therapy",
    "GoToMeeting",
    "Plan Execution",
    "Project Plan"
};
 
        Random ran = new();
        int daysCount = visibleDates.Count;
        DateTime visibleStartDate = visibleDates.FirstOrDefault();
        var appointments = new ObservableCollection<SchedulerAppointment>();
        for (int i = 0; i < 10; i++)
        {
            var startTime = visibleStartDate.AddDays(ran.Next(0, daysCount + 1)).AddHours(ran.Next(9, 16));
            appointments.Add(new SchedulerAppointment()
            {
                StartTime = startTime,
                EndTime = startTime.AddHours(1),
                Subject = subjects[ran.Next(0, subjects.Count)],
                Background = brush[ran.Next(0, brush.Count)]
            });
        }
 
        return appointments;
    }
}

 

XAML

Bind the QueryAppointmentsCommand, AppointmentsSource and ShowBusyIndicator properties from the view model for the Scheduler.

<xmlns:scheduler ="clr-namespace:Syncfusion.Maui.Scheduler;assembly=Syncfusion.Maui.Scheduler">
 
<scheduler:SfScheduler x:Name="Scheduler" 
                     View="{Binding SchedulerView, Mode=TwoWay}"
                       AllowedViews="Day,Week,WorkWeek,Agenda"
                    AppointmentsSource="{Binding Events}"
                    ShowBusyIndicator="{Binding ShowBusyIndicator}"
                    QueryAppointmentsCommand="{Binding QueryAppointmentsCommand}">
<scheduler:SfScheduler.BindingContext>
        <local:LoadOnDemandViewModel/>
</scheduler:SfScheduler.BindingContext>
</scheduler:SfScheduler>

Download the complete sample on GitHub


MAUI Scheduler load on demand


Conclusion

I hope you enjoyed learning how to load appointments on demand in the .NET MAUI Scheduler.

You can refer to our .NET MAUI Scheduler feature tour page to know about its other groundbreaking feature representations and documentation, and how to quickly get started for configuration specifications. Explore our .NET MAUI Scheduler example to understand how to create and manipulate data.

For current customers, you can check out our components from the License and Downloads page. If you are new to Syncfusion®, you can try our 30-day free trial to check out our other controls.

If you have any queries or require clarifications, please let us know in the comments section below. You can also contact us through our support forumsDirect-Trac, or feedback portal. We are always happy to assist you!

 

Did you find this information helpful?
Yes
No
Help us improve this page
Please provide feedback or comments
Comments (0)
Access denied
Access denied