Copied RSS Feed

WPF

How to Load Appointments on Demand via Web Services in WPF Scheduler

The Syncfusion WPF Scheduler control provides all the common scheduling functionalities to create and manage day-to-day business and personal appointments. When we develop WPF applications, some of the most prevalent requirements are the ability to reduce loading time and system resource consumption.

WPF Scheduler has built-in UI virtualization for better loading and view navigation performance. But that alone won’t be enough when you’re dealing with millions of events spanning multiple years. That’s where data virtualization (on-demand loading) comes in. You can provide data to the Scheduler for a single date range instead of loading all the data for multiple years.

In this blog, we are going to discuss loading appointments on demand via web services in the WPF Scheduler control. This will improve your application’s loading performance while fetching data. If you are new to the Scheduler control, please read the Getting Started article in the Scheduler documentation before proceeding.

Creating a web API service

Web services are the server-side applications that are meant to serve data or logic to various client applications. REST and SOAP are the most widely used industry-standard web service architectures.

Use the following reference to create an ASP.NET Core Web API service and host it for public access. For demo purposes, we are going to use the following hosted service.

Fetching data from Web API service

  1. Create an asynchronous method GetAppointmentsAsync and consume the API service URI.
  2. Use the GetAsync method of HttpClient to retrieve the appointment data as JSON.
  3. Modify the received JSON data into a list of appointments.
    public static class WebAPIService
        {
            /// <summary>
            /// Asynchronously fetching the data from the Web API service.
            /// </summary>
            /// <returns></returns>
            public static async Task<ObservableCollection<Event>> GetAp-pointmentsAsync()
            {
                var uri = new Uri("https://js.syncfusion.com/demos/ejservices/api/Schedule/LoadData");
                try
                {
                    var client = new HttpClient();
                    var response = await client.GetAsync(uri);
    
                    if (response.IsSuccessStatusCode)
                    {
                        var content = await response.Content.ReadAsStringAsync();
                        return (JsonConvert.DeserializeObject<ObservableCollection<Event>>(content));
                    }
                }
                catch (Exception ex)
                {
                }
                return null;
            }
        }

Creating a model class

Create a model class Event with a data structure similar to that of the data in the Web API service. Here, it should contain the appointment subject, time, and other related information.

/// <summary>   
/// Represents custom appointment properties.   
/// </summary> 
public class Event
{
   /// <summary>
   /// Gets or sets the subject of the appointment. 
   /// </summary>
   public string Subject { get; set; }

   /// <summary>
   /// Gets or sets the ID of the appointment. 
   /// </summary>
   public string Id { get; set; }

   /// <summary>
   /// Gets or sets the start time of the appointment. 
   /// </summary>
   public DateTime StartTime { get; set; }

   /// <summary>
   /// Gets or sets the end time of the appointment. 
   /// </summary>
   public DateTime EndTime { get; set; }

   /// <summary>
   /// Gets or sets the value that indicates whether the appointment is all day. 
   /// </summary>
   public bool AllDay { get; set; }

   /// <summary>
   /// Gets or sets the recurrence rule of the appointment. 
   /// </summary>
   public string RecurrenceRule { get; set; }

   /// <summary>
   /// Gets or sets the background color of the appointment. 
   /// </summary>
   public Brush Color { get; set; }
 }

Binding data to Scheduler

Create a view model SchedulerViewModel with the command property LoadOnDemandCommand to fetch appointments on demand.

public class SchedulerViewModel : NotificationObject
{
    private ObservableCollection<Event> events;
    private bool showBusyIndicator;

    /// <summary>
    /// Gets or sets load on demand command.
    /// </summary>
    public ICommand LoadOnDemandCommand { get; set; }

    /// <summary>
    /// Gets or sets web appointments data.
    /// </summary>
    public ObservableCollection<Event> WebData { get; set; }

    /// <summary>
    /// Gets or sets a value indicating whether to show the busy indicator.
    /// </summary>
    public bool ShowBusyIndicator
    {
       get { return this.showBusyIndicator; }
       set
       {
           this.showBusyIndicator = value;
           this.RaisePropertyChanged("ShowBusyIndicator");
        }
    }

    /// <summary>
    /// Gets or sets the events. 
    /// </summary>
    public ObservableCollection<Event> Events
    {
       get { return this.events; }
       set
       {
           this.events = value;
           this.RaisePropertyChanged("Events");
       }
     }

    public SchedulerViewModel()
    {
       this.Events = new ObservableCollection<Event>();
       this.LoadOnDemandCommand = new DelegateCommand(ExecuteOnDemandLoading, CanExecuteOnDemandLoading);            
    }
}

You can bind the custom appointment data with the Scheduler component using a mapping technique. Map the properties of the Event class with the relevant properties of AppointmentMapping class. Now, set the DataContext as SchedulerViewModel.

<Grid.DataContext>
  <local:SchedulerViewModel/>
</Grid.DataContext>

<syncfusion:SfScheduler x:Name="scheduler"
                        ViewType="Month"
                        ItemsSource="{Binding Events}"
                        ShowBusyIndicator="{Binding ShowBusyIndicator}"
                        LoadOnDemandCommand="{Binding LoadOnDemandCommand}">
           
<syncfusion:SfScheduler.AppointmentMapping>
  <syncfusion:AppointmentMapping
              Subject="Subject"
              StartTime="StartTime"
              EndTime="EndTime"
              IsAllDay="AllDay"
              AppointmentBackground="Color"
              RecurrenceRule="RecurrenceRule"/>
  </syncfusion:SfScheduler.AppointmentMapping>
</syncfusion:SfScheduler>

Loading appointments on demand

The Scheduler supports loading appointments on demand with a busy indicator. This improves the loading performance when you have appointments for multiple years.

The Scheduler control has LoadOnDemandCommand to load appointments on demand. While loading appointments as JSON data, we can show a busy indicator by using the ShowBusyIndicator property.

You can get the current visible date range from the command argument of LoadOnDemandCommand, fetch the appointments for the current visible date range, and update the Events property that is bound with the Scheduler ItemsSource.

public class SchedulerViewModel : NotificationObject
{
    …

    /// <summary>
    /// Method to execute load on demand command and set scheduler appointments.
    /// </summary>
    /// <param name="queryAppointments">QueryAppointmentsEventArgs object.</param>
    public async void ExecuteOnDemandLoading(object queryAppointments)
    {
        this.ShowBusyIndicator = true;
        await this.GetVisibleRangeAppointments((queryAppointments as QueryAp-pointmentsEventArgs).VisibleDateRange);
        this.ShowBusyIndicator = false;
    } 

    /// <summary>
    /// Method to check whether the load on demand command can be invoked or not.
    /// </summary>
    /// <param name="queryAppointments">QueryAppointmentsEventArgs object.</param>
    private bool CanExecuteOnDemandLoading(object queryAppointments)
    {
        return true;
    }

    /// <summary>
    /// Method to get web appointments and update them to scheduler ItemsSource.
    /// </summary>
    /// <param name="visibleDateRange">Current visible date range.</param>
    private async Task GetVisibleRangeAppointments(DateRange visibleDateRange)
    {
        if (this.WebData == null)
        {
           this.WebData = await WebAPIService.GetAppointmentsAsync();
        }

        var events = new ObservableCollection<Event>();
        foreach (Event appointment in this.WebData)
        {
           if ((visibleDateRange.StartDate <= appointment.StartTime.Date && visibleDateRange.EndDate >= appointment.StartTime.Date) ||
                (visibleDateRange.StartDate <= appointment.EndTime.Date && visibleDateRange.EndDate >= appointment.EndTime.Date))
           {
              events.Add(appointment);
           }
         }

         this.Events = events;
     }

}

Now, the Scheduler control is configured to load appointments on demand. Running the sample with the previous steps will render a scheduler with appointments.

Resource

For more information, refer to Load appointments on demand via web services in WPF Scheduler demo.

Conclusion

In this blog post, we’ve discussed loading appointments on demand in the WPF Scheduler control. You can also check out our project samples in this GitHub repository. Feel free to try out this sample and share your feedback or questions in the comments section.

You can also contact us through our support forum, Direct-Trac, or feedback portal. We are always happy to assist you.

Related blogs

Meet the Author

Jeyasri Murugan

I'm Jeyasri Murugan, a Product Manager at Syncfusion. I have experience in developing custom controls for various .NET frameworks, including .NET MAUI, Xamarin, WPF, WinUI, and UWP.