This tutorial shows how to use the DayPilot Pro MVC Scheduler with MVC 4 and Razor engine. It will load scheduled events from a database (SQL Server), and allow event creating using TimeRangeSelected event and event moving using drag&drop.
Included
- DayPilot Pro for MVC 2018.1 Trial
- Sample SQL Server Database
- C# Source Code
- VB.NET Source Code
- Visual Studio 2017 project
Features
- Displaying events for multiple resources (rooms)
- Drag and drop event moving
- Drag and drop event creating
- Event details editing using a modal dialog
- CSS3 theme
- Displaying status messages
Requirements
- Requires ASP.NET MVC 4 installed globally (see also ASP.NET MVC 4 Scheduler Quick Start Project which uses ASP.NET MVC 4 as a NuGet dependency)
License
Licensed for testing and evaluation purposes. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for ASP.NET MVC. Buy a license.
Installation
DLL
- Put DayPilot.Mvc.dll in the bin directory of the web application.
- Add it to project references if you are using a compiled web project.
Scripts
Include the DayPilot script in the web page (the scripts can be found in Scripts/DayPilot directory):
- daypilot-all.min.js
All the scripts are included in the site template (Views/Shared/_Layout.cshtml or Views/Shared/_Layout.vbhtml):
<head> <!-- ... --> <script src="@Url.Content("~/Scripts/DayPilot/daypilot-all.min.js")" type="text/javascript"></script>
</head>
CSS Themes
Copy the Demo/Themes directory from the DayPilot demo project to Themes directory.
Include Themes/scheduler_white.css stylesheet in the web page:
<head> <!-- ... --> <link href="@Url.Content("~/Themes/scheduler_white.css")" rel="stylesheet" type="text/css" />
</head>
MVC View
Add the ASP.NET MVC scheduler control to the view (Views/Home/Index.cshtml or Index.vbhtml):
C#
@using DayPilot.Web.Mvc;
@using DayPilot.Web.Mvc.Events.Scheduler;
@using DayPilot.Web.Mvc.Enums; @using DayPilot.Web.Mvc.Enums.Scheduler;
@Html.DayPilotScheduler("dps", new DayPilotSchedulerConfig{})
VB.NET
@imports DayPilot.Web.Mvc @imports DayPilot.Web.Mvc.Events.Scheduler @imports DayPilot.Web.Mvc.Enums @imports DayPilot.Web.Mvc.Enums.Scheduler @Html.DayPilotScheduler("dps", new DayPilotSchedulerConfig)
This will add an empty Scheduler with default settings.
In order to show calendar data, we need to specify the backend url:
C#
@Html.DayPilotScheduler("dps", new DayPilotSchedulerConfig { BackendUrl = Url.Content("~/Scheduler/Backend") })
VB.NET
@Html.DayPilotScheduler("dps", new DayPilotSchedulerConfig With
{
.BackendUrl = Url.Content("~/Scheduler/Backend")
})
Apply a CSS Theme
Apply the "scheduler_white" CSS theme by setting Theme="scheduler_white".
C#
@Html.DayPilotScheduler("dps", new DayPilotSchedulerConfig { BackendUrl = Url.Content("~/Scheduler/Backend"), Theme = "scheduler_white" })
VB.NET
@Html.DayPilotScheduler("dps", new DayPilotSchedulerConfig With
{
.BackendUrl = Url.Content("~/Scheduler/Backend"), .Theme = "scheduler_white"
})
Note: You can create a custom theme in the online CSS theme designer.
Backend MVC Controller
Create a new SchedulerController class that will handle the backend requests. Add a Backend method:
C#
using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Web; using System.Web.Mvc; using DayPilot.Web.Mvc; using DayPilot.Web.Mvc.Enums; using DayPilot.Web.Mvc.Events.Scheduler; namespace TutorialCS.Controllers { public class SchedulerController : Controller { public ActionResult Backend() { return null; } } }
VB.NET
Imports System Imports System.Collections.Generic Imports System.Data Imports System.Linq Imports System.Web Imports System.Web.Mvc Imports DayPilot.Web.Mvc Imports DayPilot.Web.Mvc.Enums Imports DayPilot.Web.Mvc.Events.Scheduler Namespace TutorialCS.Controllers Public Class SchedulerController Inherits System.Web.Mvc.Controller Function Backend() As ActionResult Return Nothing End Function End Class End Namespace
Create a new Dps class that will inherit from DayPilot.Web.Mvc.DayPilotScheduler:
C#
public class Dps : DayPilotScheduler { }
VB.NET
Public Class Dps Inherits DayPilotScheduler End Class
Modify the Backend action of the Scheduler controller to pass control to a new instance of the Dps class:
C#
public class SchedulerController : Controller { public ActionResult Backend() { return new Dps().CallBack(this); } }
VB.NET
Public Class SchedulerController Inherits System.Web.Mvc.Controller Function Backend() As ActionResult Return New Dps().CallBack(Me) End Function End Class
Now override OnInit() method of the DayPilotScheduler class in the Dps class in order to handle the Init event:
C#
public class Dps : DayPilotScheduler { protected override void OnInit(InitArgs initArgs) { Events = new EventManager().FilteredData(StartDate, StartDate.AddDays(Days)).AsEnumerable();
DataStartField = "eventstart";
DataEndField = "eventend";
DataTextField = "name";
DataIdField = "id";
DataResourceField = "resource";
UpdateWithMessage("Welcome!"); } }
VB.NET
Public Class Dps Inherits DayPilotScheduler Protected Overrides Sub OnInit(ByVal e As DayPilot.Web.Mvc.Events.Calendar.InitArgs) Dim em = New EventManager() Events = em.FilteredData(StartDate, StartDate.AddDays(Days)).AsEnumerable DataStartField = "eventstart" DataEndField = "eventend" DataTextField = "name" DataIdField = "id"
DataResourceField = "resource" UpdateWithMessage("Welcome!") End Sub End Class
This OnInit() method does three things:
- It loads the event set to Events property.
- It maps the event set fields (id, start, end, text, resource) to DayPilot fields.
- It tells the Scheduler to refresh the events and show a welcome message on the client side.
EventManager is a helper class that loads data from a database:
C#
public class EventManager { public DataTable FilteredData(DateTime start, DateTime end) { SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM [event] WHERE NOT (([eventend] <= @start) OR ([eventstart] >= @end))", ConfigurationManager.ConnectionStrings["daypilot"].ConnectionString); da.SelectCommand.Parameters.AddWithValue("start", start); da.SelectCommand.Parameters.AddWithValue("end", end); DataTable dt = new DataTable(); da.Fill(dt); return dt; } }
VB.NET
Public Class EventManager Public Function FilteredData(ByVal start As DateTime, ByVal end_ As DateTime) As DataTable Dim da As SqlDataAdapter = New SqlDataAdapter("SELECT * FROM [event] WHERE NOT (([eventend] <= @start) OR ([eventstart] >= @end))", ConfigurationManager.ConnectionStrings("daypilot").ConnectionString) da.SelectCommand.Parameters.AddWithValue("start", start) da.SelectCommand.Parameters.AddWithValue("end", end_) Dim dt = New DataTable da.Fill(dt) Return dt End Function End Class
Define Resources (Rows)
You can load resources using the Resources collection on the server side.
The Resources collection is persisted during subsequent callback calls so it is enough to load them during the init callback:
C#
protected override void OnInit(InitArgs e) { LoadResources(); UpdateWithMessage("Welcome!", CallBackUpdateType.Full); } private void LoadResources() { foreach (DataRow r in new EventManager().GetResources().Rows) { Resources.Add((string) r["name"], Convert.ToString(r["id"])); } }
VB.NET
Protected Overrides Sub OnInit(ByVal e As InitArgs) LoadResources() UpdateWithMessage("Welcome!", CallBackUpdateType.Full) End Sub Private Sub LoadResources() For Each r As DataRow In (New EventManager()).GetResources().Rows Resources.Add(CStr(r("name")), Convert.ToString(r("id"))) Next r End Sub
Adding a New Event
Now we will enable drag and drop event creating. Add TimeRangeSelectedHandling property to the scheduler configuration in the MVC view:
C#
@Html.DayPilotScheduler("dps", new DayPilotSchedulerConfig { BackendUrl = Url.Content("~/Scheduler/Backend"), TimeRangeSelectedHandling = TimeRangeSelectedHandlingType.JavaScript, TimeRangeSelectedJavaScript = "modal('Event/Create?start=' + start + '&end=' + end + '&resource=' + resource)" })
VB.NET
@Html.DayPilotCalendar("dps", new DayPilotSchedulerConfig With { .BackendUrl = Url.Content("~/Scheduler/Backend"), .TimeRangeSelectedHandling = TimeRangeSelectedHandlingType.JavaScript, .TimeRangeSelectedJavaScript = "modal('Event/Create?start=' + start + '&end=' + end + '&resource=' + resource)" })
The modal() function uses DayPilot.Modal class to display a modal popup with new event details:
<script type="text/javascript"> function modal(url) { var m = new DayPilot.Modal(); m.closed = function () { if (this.result == "OK") { dps.commandCallBack('refresh'); } dps.clearSelection(); }; m.showUrl(url); } </script>
After the new event is inserted in the database, the modal popup refreshes the scheduler using .commandCallBack(). The .commandCallBack() method fires OnCommand() on the server side:
C#
protected override void OnCommand(CommandArgs e) { switch (e.Command) { case "refresh": Events = new EventManager().FilteredData(StartDate, StartDate.AddDays(Days)).AsEnumerable(); DataStartField = "eventstart"; DataEndField = "eventend"; DataTextField = "name"; DataIdField = "id"; DataResourceField = "resource"; Update(); break; } }
VB.NET
Protected Overrides Sub OnCommand(ByVal e As CommandArgs) Select Case e.Command Case "refresh" Dim em = New EventManager() Events = em.FilteredData(StartDate, StartDate.AddDays(Days)).AsEnumerable DataStartField = "eventstart" DataEndField = "eventend" DataTextField = "name" DataIdField = "id" DataResourceField = "resource" Update() End Select End Sub
The OnCommand() method does three things:
- It loads the event set to Events property.
- It maps the event set fields (id, start, end, text, resource) to DayPilot fields.
- It tells the Scheduler to refresh the events using Update().
You can see that the steps 2-4 are the same as in OnInit(). We can move the events reloading to OnFinish() method which is called during every CallBack after the main event handler.
C#
protected override void OnInit(InitArgs initArgs) { UpdateWithMessage("Welcome!"); } protected override void OnCommand(CommandArgs e) { switch (e.Command) { case "refresh": Update(); break; } } protected override void OnFinish() { // update was not requested in the event handler using Update() or UpdateWithMessage() // skip event reloading if (UpdateType == CallBackUpdateType.None) { return; } Events = new EventManager().FilteredData(StartDate, StartDate.AddDays(Days)).AsEnumerable(); DataStartField = "eventstart"; DataEndField = "eventend"; DataTextField = "name"; DataIdField = "id"; DataResourceField = "resource"; }
VB.NET
Protected Overrides Sub OnInit(ByVal e As DayPilot.Web.Mvc.Events.Calendar.InitArgs) UpdateWithMessage("Welcome!") End Sub Protected Overrides Sub OnCommand(ByVal e As CommandArgs) Select Case e.Command Case "refresh" Update() End Select End Sub Protected Overrides Sub OnFinish() REM update was not requested in the event handler using Update() or UpdateWithMessage() REM skip event reloading If (UpdateType = Enums.CallBackUpdateType.None) Then Return End If Dim em = New EventManager() Events = em.FilteredData(StartDate, StartDate.AddDays(Days)).AsEnumerable DataStartField = "eventstart" DataEndField = "eventend" DataTextField = "name" DataIdField = "id" DataResourceField = "resource" End Sub
Event Moving
Similar steps have to be applied in order to enable event moving using drag and drop.
Add EventMoveHandling property to the view:
C#
@Html.DayPilotScheduler("dps", new DayPilotSchedulerConfig { BackendUrl = Url.Content("~/Scheduler/Backend"), EventMoveHandling = EventMoveHandlingType.CallBack, TimeRangeSelectedHandling = TimeRangeSelectedHandlingType.CallBack })
VB.NET
@Html.DayPilotCalendar("dps", new DayPilotSchedulerConfig With { .BackendUrl = Url.Content("~/Scheduler/Backend"), .EventMoveHandling = EventMoveHandlingType.CallBack, .TimeRangeSelectedHandling = TimeRangeSelectedHandlingType.CallBack })
Override OnEventMove() method in the Dpc class:
C#
protected override void OnEventMove(EventMoveArgs e) { new EventManager().EventMove(e.Id, e.NewStart, e.NewEnd, e.NewResource); UpdateWithMessage("The event was moved."); }
VB.NET
Protected Overrides Sub OnEventMove(ByVal e As DayPilot.Web.Mvc.Events.Calendar.EventMoveArgs) Dim em = New EventManager() em.EventMove(e.Id, e.NewStart, e.NewEnd, e.NewResource)
UpdateWithMessage("The event was moved.") End Sub