Virtual Scrolling in ASP.NET MVC Scheduler
To achieve better performance in the Scheduler when loading a large number of resources and events, virtual scrolling support has been added to load a large set of resources and events instantly as you scroll. You can dynamically load a large number of resources and events in the Scheduler by setting true on the AllowVirtualScrolling property within the view-specific settings. Virtual loading of events is also possible in the Agenda view by setting the AllowVirtualScrolling property to true within the Agenda view-specific settings.
@using Syncfusion.EJ2.Schedule
@(Html.EJS().Schedule("schedule")
.Width("100%")
.Height("650px")
.SelectedDate(new DateTime(DateTime.Today.Year, 4, 1))
.CurrentView(View.TimelineMonth)
.Views(view => {
view.Option(View.TimelineMonth).AllowVirtualScrolling(true).Add();
view.Option(View.TimelineYear).Orientation(Orientation.Vertical).AllowVirtualScrolling(true).Add();
})
.Group(group => group.EnableCompactView(false).Resources(ViewBag.Resource))
.Resources(res => {
res.DataSource(ViewBag.resourcesData).Field("ResourceId").Title("Resource").Name("Resources").TextField("Text").IdField("Id").ColorField("Color").AllowMultiple(true).Add();
})
.EventSettings(new ScheduleEventSettings { DataSource = ViewBag.datasource })
.Render()
)public ActionResult Index()
{
ViewBag.datasource = this.generateStaticEvents(new DateTime(2018, 4, 1), 300, 12);
ViewBag.resourcesData = this.GenerateResourceData(1, 300);
string[] resources = new string[] { "Resources" };
ViewBag.Resource = resources;
return View();
}
private List<ResourceData> GenerateResourceData(int start, int end)
{
List<ResourceData> resources = new List<ResourceData>(300);
var colors = new string[] { "#ff8787", "#9775fa", "#748ffc", "#3bc9db", "#69db7c",
"#fdd835", "#748ffc", "#9775fa", "#df5286", "#7fa900",
"#fec200", "#5978ee", "#00bdae", "#ea80fc"};
for (int a = start; a <= end; a++)
{
int index = a % colors.Length;
index = index == 0 ? (colors.Length / a):index;
resources.Add(new ResourceData
{
Id = a,
Text = "Resource " + a,
Color = colors[index]
});
}
return resources;
}
private List<EventData> generateStaticEvents(DateTime date, int v1, int v2)
{
List<EventData> data = new List<EventData>(3600);
var id = 1;
for (var i = 0; i < 300; i++)
{
Random random= new Random();
List<int> listNumbers = new List<int>();
int[] randomCollection = new int[24];
int number;
int max = 30;
for (int a = 0; a < 12; a++)
{
do
{
number = random.Next(max);
} while (listNumbers.Contains(number));
listNumbers.Add(number);
var startDate = date.AddDays(number);
startDate = startDate.AddMilliseconds((((number % 10) * 10) * (1000 * 60)));
var endDate = startDate.AddMilliseconds(((1440 + 30) * (1000 * 60)));
data.Add(new EventData
{
Id = id,
Subject = "Event #" + id,
StartTime = startDate,
EndTime = endDate,
IsAllDay = (id % 10 == 0) ? false : true,
ResourceId = i + 1
});
id++;
}
}
return data;
}
class EventData
{
public int Id { get; set; }
public string Subject { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public bool IsAllDay { get; set; }
public int ResourceId { get; set; }
}
class ResourceData
{
public int Id { get; set; }
public string Text { get; set; }
public string Color { get; set; }
}NOTE
The virtual loading of resources and events is currently not supported in the
MonthAgenda,Year, andTimelineYear(Horizontal Orientation) views. By default, the Scheduler renders only the visible appointments. You can increase or decrease the preloaded appointment buffer using theOverScanCountproperty to ensure smooth scrolling.
Enabling lazy loading for appointments
The lazy loading feature provides a convenient way to efficiently load resource appointments into the Scheduler using an on-demand approach. With this feature, you can seamlessly load a large volume of appointment data into the Scheduler without experiencing any performance degradation.
By default, the Scheduler fetches all relevant appointments from the server within the current date range. However, enabling this feature triggers query requests to the server for appointment retrieval whenever new resources are rendered due to scroll actions. These queries contain the resource IDs of the currently displayed resources along with the current date range, which can be passed as a comma-separated string. In the server controller, these resource IDs are parsed to filter the necessary appointments to render in the Scheduler.
When this feature is enabled, the Scheduler is capable of fetching events from remote services only for the current viewport, optimizing data retrieval. The remaining appointment data is fetched from the server on-demand, based on the resources rendered in the current viewport as you scroll through the Scheduler content.
To enable this feature, set the EnableLazyLoading property to true within the view-specific settings.
@using Syncfusion.EJ2.Schedule
@(Html.EJS().Schedule("schedule")
.Width("100%")
.Height("650px")
.SelectedDate(new DateTime(DateTime.Today.Year, 4, 1))
.CurrentView(View.TimelineMonth)
.Views(view => {
view.Option(View.TimelineMonth).EnableLazyLoading(true).Add();
})
.Group(group => group.EnableCompactView(false).Resources(ViewBag.Resource))
.Resources(res => {
res.DataSource(ViewBag.resourcesData).Field("ResourceId").Title("Resource").Name("Resources").TextField("Text").IdField("Id").ColorField("Color").Add();
}).EventSettings(es => es.DataSource(dataManager =>
{
dataManager.Url("https://services.syncfusion.com/aspnet/production/api/VirtualEventData").CrossDomain(true).Adaptor("WebApiAdaptor");
})).Readonly(true)
.Render()
)public ActionResult Index()
{
ViewBag.resourcesData = this.GenerateResourceData(1, 1000);
string[] resources = new string[] { "Resources" };
ViewBag.Resource = resources;
return View();
}
private List<ResourceData> GenerateResourceData(int start, int end)
{
List<ResourceData> resources = new List<ResourceData>(300);
var colors = new string[] { "#ff8787", "#9775fa", "#748ffc", "#3bc9db", "#69db7c",
"#fdd835", "#748ffc", "#9775fa", "#df5286", "#7fa900",
"#fec200", "#5978ee", "#00bdae", "#ea80fc"};
for (int a = start; a <= end; a++)
{
int index = a % colors.Length;
index = index == 0 ? (colors.Length / a):index;
resources.Add(new ResourceData
{
Id = a,
Text = "Resource " + a,
Color = colors[index]
});
}
return resources;
}
class ResourceData
{
public int Id { get; set; }
public string Text { get; set; }
public string Color { get; set; }
}Here’s the server-side controller code that retrieves appointment data based on the resource IDs provided as query parameters:
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.OData.Query;
namespace LazyLoadingServices.Controllers
{
public class VirtualEventDataController : Controller
{
private readonly EventsContext dbContext;
[HttpGet]
[EnableQuery]
[Route("api/VirtualEventData")]
public IActionResult GetData([FromQuery] Params param)
{
IQueryable<EventData> query = dbContext.Events;
// Filter the appointment data based on the ResourceId query params.
if (!string.IsNullOrEmpty(param.ResourceId))
{
string[] resourceId = param.ResourceId.Split(',');
query = query.Where(data => resourceId.Contains(data.ResourceId.ToString()));
}
return Ok(query.ToList());
}
}
public class Params
{
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public string ResourceId { get; set; }
}
}Note:
- The property will be effective when a large number of resources and appointments are bound to the Scheduler.
- This property is applicable only when resource grouping is enabled in the Scheduler.
NOTE
You can refer to our ASP.NET MVC Scheduler feature tour page for its groundbreaking feature representations. You can also explore our ASP.NET MVC Scheduler example to know how to present and manipulate data.