Sample Project

The sample project includes:

Features

  • Three shifts per day (7am - 3pm, 3pm - 11pm, 11pm - 7am)

  • Time headers grouped by day and month

  • Highlighting weekend shifts

  • Displaying nurses on the vertical (Y) axis

  • Displaying the timeline on the horizontal (X) axis

  • SQL Server database

See also an ASP.NET Core tutorial that implements shift scheduling for multiple locations/positions:

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 WebForms.

How to initialize the shift Scheduler control?

The first step is to add the <DayPilotScheduler> tag to your ASP.NET WebForm page. The ASP.NET scheduler control lets you create the shift overview and provide the UI necessary for planning the nurse shifts.

<DayPilot:DayPilotScheduler
  ID="DayPilotScheduler1" 
  runat="server" 
  />

How to load nurse data?

We will use the Resources property of the ASP.NET scheduler to display the nurses in Scheduler rows.

The nurses will be displayed on the vertical axis.

protected void Page_Load(object sender, EventArgs e)
{
  if (!IsPostBack)
  {
      // ...
      LoadResources();
      // ...
  }
}

private void LoadResources()
{
  SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM [resource] ORDER BY [resource_name]", ConfigurationManager.ConnectionStrings["daypilot"].ConnectionString);
  DataTable dt = new DataTable();
  da.Fill(dt);

  DayPilotScheduler1.Resources.Clear();
  foreach(DataRow dr in dt.Rows)
  {
      string name = (string) dr["resource_name"];
      string id = Convert.ToString(dr["resource_id"]);
      DayPilotScheduler1.Resources.Add(name, id);
  }
r
}

How to define nurse shifts?

The scheduler control can generate the timeline (set of time cells) automatically from the start date and number of days.

We need a custom cell start and end so we will create a custom timeline:

  • Set Scale property to Manual

  • Add the custom time cells to Timeline collection.

protected void Page_Load(object sender, EventArgs e)
{
  if (!IsPostBack)
  {
      LoadTimeline(DateTime.Today);
  }
}

private void LoadTimeline(DateTime date)
{
  DayPilotScheduler1.StartDate = date; // required for later refreshes (will be persisted)
  DayPilotScheduler1.Scale = TimeScale.Manual;

  const int firstShiftStartHour = 7; // first shift starts at 7 am
  const int shiftDurationHours = 8; // one shift takes 8 hours

  DateTime firstDayOfMonth = new DateTime(date.Year, date.Month, 1); // first day of month
  int days = DateTime.DaysInMonth(firstDayOfMonth.Year, firstDayOfMonth.Month);
  DateTime start = firstDayOfMonth.AddHours(firstShiftStartHour); 
  DateTime end = firstDayOfMonth.AddDays(days);

  while (start < end)
  {
      DayPilotScheduler1.Timeline.Add(start, start.AddHours(shiftDurationHours));
      start = start.AddHours(shiftDurationHours);
  }
}

How to customize the Scheduler time header?

We will customize the time header cells (especially the date format) using BeforeTimeHeaderRender event handler.

protected void DayPilotScheduler1_OnBeforeTimeHeaderRender(object sender, BeforeTimeHeaderRenderEventArgs e)
{
  if (e.Level == 1)
  {
      e.InnerHTML = e.Start.ToString("dddd, MMMM d");
  }
  if (e.Level == 2)
  {
      string start = TimeFormatter.GetHour(e.Start, TimeFormat.Clock12Hours, "{0}{1}").ToLower();
      string end = TimeFormatter.GetHour(e.End, TimeFormat.Clock12Hours, "{0}{1}").ToLower();
      
      e.InnerHTML = start + "-" + end;
      
  }
}

How to load the shift assignment data?

Add the database column bindings to the scheduler control:

<DayPilot:DayPilotScheduler
  ID="DayPilotScheduler1" 
  runat="server" 
  
  DataEndField="shift_start"
  DataStartField="shift_end" 
  DataTextField="shift_name" 
  DataIdField="shift_id" 
  DataResourceField="resource_id"
  />

Load the database records:

protected void Page_Load(object sender, EventArgs e)
{
  if (!IsPostBack)
  {
      DayPilotScheduler1.DataSource = DbLoadShiftData(DayPilotScheduler1.VisibleStart, DayPilotScheduler1.VisibleEnd);
      DayPilotScheduler1.DataBind();
  }
}

private DataTable DbLoadShiftData(DateTime start, DateTime end)
{
  SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM [shift] WHERE NOT (([shift_end] <= @start) OR ([shift_start] >= @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;
}