Late last year (v20.2), we added on-demand data loading support to our WPF Scheduler control. In this post, we’ll describe how you can use the WPF Scheduler’s API to configure data loading logic within your WPF app.
Performance Impact
Fetching data from the source on demand is a common technique to enhance the startup time for applications with large datasets. To help you estimate the benefit, we measured how long it takes for the Scheduler control to load appointments:
These measurements do not take into account the time it takes to load data items from the source. The performance gain from loading only a part of the data will be higher for slower databases and services.
Getting Started with On-Demand Loading
To enable on-demand data loading, you must handle the DataSource.FetchAppointments event (there is a separate DataSource.FetchTimeRegions event for time regions). When you handle these events, the DevExpress WPF Scheduler loads data only for its currently visible time interval. When a user navigates from one time period to another, our WPF Scheduler queries more information (as necessary) from the data source. Loaded data is cached to reduce query frequency.
To reduce query frequency further, our WPF Scheduler extends the time interval for which to load data to the DataSource.FetchRange property value. The default FetchRange is 1 month. The Scheduler only recalculates this time interval once the user scrolls outside of this range:
Implementation
The following code sample demonstrates how to introduce on-demand data loading for a DbContext data source:
// Data context
public class SchedulingDataContext : DbContext {
public SchedulingDataContext() : base(CreateConnection(), true) { }
static DbConnection CreateConnection() {
//...
}
// Data items
public DbSet<AppointmentEntity> AppointmentEntities { get; set; }
//...
}
// Event implementation
void dataSource_FetchAppointments(object sender, DevExpress.Xpf.Scheduling.FetchDataEventArgs e) {
// Pass data objects to the event's Result property
e.Result = dbContext.AppointmentEntities.Where(
// The search query.
// Use the item's QueryStart and QueryEnd properties to calculate the correct interval
// as they take recurrence patterns into account.
// The event's Interval property returns the time interval for which to load data objects.
// Its value is the SchedulerControl.VisibleIntervals extended to the DataSource.FetchRange property value in both directions.
x => x.QueryStart <= e.Interval.End && x.QueryEnd >= e.Interval.Start)
.ToArray();
}
The Where method’s argument in this snippet is a basic search query with no filtering involved. You can use the FetchDataEventArgs.GetFetchExpression method instead to simplify the implementation:
void FetchAppointments(FetchDataEventArgs e) {
e.Result = dbContext.AppointmentEntities
.Where(e.GetFetchExpression<AppointmentEntity>()).ToArray();
}
Sync the Scheduler and the Source
To sync the data source and the Scheduler (with partially loaded data), you need to manually save changes. Built-in CRUD events simplify this requirement. You can write a single handler for all four events:
<dxsch:SchedulerControl
AppointmentAdded="ProcessChanges"
AppointmentEdited="ProcessChanges"
AppointmentRemoved="ProcessChanges"
AppointmentRestored="ProcessChanges"/>
void ProcessChanges(object sender, AppointmentCRUDEventArgs e) {
db.Appointments.AddRange(e.AddToSource.Select(x => (Appointment)x.SourceObject));
db.Appointments.RemoveRange(e.DeleteFromSource.Select(x => (Appointment)x.SourceObject));
db.SaveChanges();
}
If you’d like to learn more about on-demand data loading and if you have the DevExpress WPF Components installed on your machine, click the link below to launch our sample demo:
On-Demand Data Loading Demo: dxdemo://Wpf/DXScheduling/MainDemo/OnDemandDataLoading
Should you have questions about On-Demand Data Loading, please post comments/feedback below.