Click here to Skip to main content
15,891,905 members
Articles / Web Development / HTML

DayPilot Scheduler Control for ASP.NET

Rate me:
Please Sign up or sign in to vote.
4.91/5 (54 votes)
20 Jan 2016Apache4 min read 306.3K   8K   276  
Flexible open-source scheduler control (resource booking, project management, timeline and free/busy visualization, Gantt)
/*
Copyright � 2005 - 2008 Annpoint, s.r.o.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

-------------------------------------------------------------------------

NOTE: Reuse requires the following acknowledgement (see also NOTICE):
This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o.
*/

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing; 
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using DayPilot.Web.Ui.Design;

namespace DayPilot.Web.Ui
{
    /// <summary>
    /// DayPilot is a component for showing a day schedule.
    /// </summary>
    [ToolboxBitmap(typeof(Calendar))]
    [Designer(typeof(DayPilotCalendarDesigner))]
    [AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    public partial class DayPilotCalendar : DataBoundControl, IPostBackEventHandler
    {
        internal Day[] days;

        private string dataStartField;
        private string dataEndField;
        private string dataTextField;
        private string dataValueField;

        // day header
        private bool showHeader = true;
        private int headerHeight = 21;
        private string headerDateFormat = "d";

        private ArrayList items;

        /// <summary>
        /// Event called when the user clicks an event in the calendar. It's only called when EventClickHandling is set to PostBack.
        /// </summary>
        [Category("User actions")]
        [Description("Event called when the user clicks an event in the calendar.")]
        public event EventClickDelegate EventClick;

        /// <summary>
        /// Event called when the user clicks a free space in the calendar. It's only called when FreeTimeClickHandling is set to PostBack.
        /// </summary>
        [Category("User actions")]
        [Description("Event called when the user clicks a free space in the calendar.")]
        public event FreeClickDelegate FreeTimeClick;


        #region Viewstate

        /// <summary>
        /// Loads ViewState.
        /// </summary>
        /// <param name="savedState"></param>
        protected override void LoadViewState(object savedState)
        {
            if (savedState == null)
                return;

            object[] vs = (object[])savedState;

            if (vs.Length != 2)
                throw new ArgumentException("Wrong savedState object.");

            if (vs[0] != null)
                base.LoadViewState(vs[0]);

            if (vs[1] != null)
                items = (ArrayList)vs[1];

        }

        /// <summary>
        /// Saves ViewState.
        /// </summary>
        /// <returns></returns>
        protected override object SaveViewState()
        {
            object[] vs = new object[2];
            vs[0] = base.SaveViewState();
            vs[1] = items;

            return vs;
        }

        #endregion

        #region PostBack


        /// <summary>
        /// 
        /// </summary>
        /// <param name="eventArgument"></param>
        public void RaisePostBackEvent(string eventArgument)
        {

            if (eventArgument.StartsWith("PK:"))
            {
                string pk = eventArgument.Substring(3, eventArgument.Length - 3);
                if (EventClick != null)
                    EventClick(this, new EventClickEventArgs(pk));
            }
            else if (eventArgument.StartsWith("TIME:"))
            {
                DateTime time = Convert.ToDateTime(eventArgument.Substring(5, eventArgument.Length - 5));
                if (FreeTimeClick != null)
                    FreeTimeClick(this, new FreeClickEventArgs(time));
            }
            else
            {
                throw new ArgumentException("Bad argument passed from postback event.");
            }
        }

        #endregion

        #region Rendering

        /// <summary>
        /// Renders the component HTML code.
        /// </summary>
        /// <param name="output"></param>
        protected override void Render(HtmlTextWriter output)
        {
            loadEventsToDays();

            // <table>
            output.AddAttribute("id", ClientID);
            output.AddAttribute("cellpadding", "0");
            output.AddAttribute("cellspacing", "0");
            output.AddAttribute("border", "0");
            output.AddAttribute("width", Width.ToString());
            output.AddStyleAttribute("border-bottom", "1px solid " + ColorTranslator.ToHtml(BorderColor));
            output.AddStyleAttribute("text-align", "left");
            output.RenderBeginTag("table");

            // <tr>
            output.RenderBeginTag("tr");

            // <td>
            output.AddAttribute("valign", "top");
            output.RenderBeginTag("td");

            if (ShowHours)
                renderHourNamesTable(output);

            // </td>
            output.RenderEndTag();

            // <td>
            output.AddAttribute("width", "100%");
            output.AddAttribute("valign", "top");
            output.RenderBeginTag("td");

            renderEventsAndCells(output);

            // </td>
            output.RenderEndTag();
            // </tr>
            output.RenderEndTag();
            // </table>
            output.RenderEndTag();
        }


        private void renderHourNamesTable(HtmlTextWriter output)
        {
            //			output.WriteLine("<!-- hours table  -->");
            output.AddAttribute("cellpadding", "0");
            output.AddAttribute("cellspacing", "0");
            output.AddAttribute("border", "0");
            output.AddAttribute("width", this.HourWidth.ToString());

            output.AddStyleAttribute("border-left", "1px solid " + ColorTranslator.ToHtml(BorderColor));
            output.RenderBeginTag("table");

            // <tr> first emtpy
            output.AddStyleAttribute("height", "1px");
            output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(BorderColor));
            output.RenderBeginTag("tr");

            output.RenderBeginTag("td");
            output.RenderEndTag();

            // </tr> first empty
            output.RenderEndTag();

            if (this.ShowHeader)
                renderHourHeader(output);

            for (DateTime i = visibleStart; i < visibleEnd; i = i.AddHours(1))
            {
                renderHourTr(output, i);
            }

            // </table>
            output.RenderEndTag();

        }


        private void renderHourTr(HtmlTextWriter output, DateTime i)
        {

            // <tr>
            output.AddStyleAttribute("height", HourHeight + "px");
            output.RenderBeginTag("tr");

            // <td>
            output.AddAttribute("valign", "bottom");
            output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(HourNameBackColor));
            output.AddStyleAttribute("cursor", "default");
            output.RenderBeginTag("td");

            // <div> block
//            DivWriter divBlock = new DivWriter();
            output.AddStyleAttribute("display", "block");
            output.AddStyleAttribute("border-bottom", "1px solid " + ColorTranslator.ToHtml(HourNameBorderColor));
            output.AddStyleAttribute("height", (HourHeight - 1) + "px");
            output.AddStyleAttribute("text-align", "right");
            output.RenderBeginTag("div");
//            output.Write(divBlock.BeginTag());

            // <div> text
//            DivWriter divText = new DivWriter();
            output.AddStyleAttribute("padding", "2px");
            output.AddStyleAttribute("font-family", HourFontFamily);
            output.AddStyleAttribute("font-size", HourFontSize);
            output.RenderBeginTag("div");
//            output.Write(divText.BeginTag());

            int hour = i.Hour;
            bool am = (i.Hour / 12) == 0;
            if (TimeFormat == TimeFormat.Clock12Hours)
            {
                hour = i.Hour % 12;
                if (hour == 0)
                    hour = 12;
            }

            output.Write(hour);
            output.Write("<span style='font-size:10px; vertical-align: super; '>&nbsp;");
            if (TimeFormat == TimeFormat.Clock24Hours)
            {
                output.Write("00");
            }
            else
            {
                if (am)
                    output.Write("AM");
                else
                    output.Write("PM");
            }
            output.Write("</span>");

            output.RenderEndTag();
            output.RenderEndTag();
//            output.Write(divText.EndTag());
//            output.Write(divBlock.EndTag());
            output.RenderEndTag(); // </td>
            output.RenderEndTag(); // </tr>
        }


        private void renderHourHeader(HtmlTextWriter output)
        {

            // <tr>
            output.AddStyleAttribute("height", (this.HeaderHeight) + "px");
            output.RenderBeginTag("tr");

            // <td>
            output.AddAttribute("valign", "bottom");
            output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(HourNameBackColor));
            output.AddStyleAttribute("cursor", "default");
            output.RenderBeginTag("td");

            // <div> block
//            DivWriter divBlock = new DivWriter();
            output.AddStyleAttribute("display", "block");
            output.AddStyleAttribute("border-bottom", "1px solid " + ColorTranslator.ToHtml(BorderColor));
            output.AddStyleAttribute("text-align", "right");
            output.RenderBeginTag("div");
//            output.Write(divBlock.BeginTag());

            // <div> text
//            DivWriter divText = new DivWriter();
            output.AddStyleAttribute("padding", "2px");
            output.AddStyleAttribute("font-size", "6pt");
            output.RenderBeginTag("div");
//            output.Write(divText.BeginTag());

            output.Write("&nbsp;");

            output.RenderEndTag();
            output.RenderEndTag();
//            output.Write(divText.EndTag());
//            output.Write(divBlock.EndTag());
            output.RenderEndTag(); // </td>
            output.RenderEndTag(); // </tr>
        }

        private void renderEventsAndCells(HtmlTextWriter output)
        {
            //			output.WriteLine("<!-- cells table -->");

            if (days != null)
            {
                // <table>
                output.AddAttribute("cellpadding", "0");
                output.AddAttribute("cellspacing", "0");
                output.AddAttribute("border", "0");
                output.AddAttribute("width", "100%");
                output.AddStyleAttribute("border-left", "1px solid " + ColorTranslator.ToHtml(BorderColor));
                output.RenderBeginTag("table");

                // <tr> first
                output.AddStyleAttribute("height", "1px");
                output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(BorderColor));
                output.RenderBeginTag("tr");

                renderEventTds(output);

                // </tr> first
                output.RenderEndTag();

                // header
                if (this.ShowHeader)
                {
                    renderDayHeaders(output);
                }
            }

            output.WriteLine("<!-- empty cells -->");

            // render all cells

            for (DateTime i = visibleStart; i < visibleEnd; i = i.AddHours(1))
            {

                // <tr> first half-hour
                output.RenderBeginTag("tr");

                addHalfHourCells(output, i, true, false);

                // </tr>
                output.RenderEndTag();

                // <tr> second half-hour
                output.AddStyleAttribute("height", (HourHeight / 2) + "px");
                output.RenderBeginTag("tr");

                bool isLastRow = (i == visibleEnd.AddHours(-1));
                addHalfHourCells(output, i, false, isLastRow);

                // </tr>
                output.RenderEndTag();
            }

            // </table>
            output.RenderEndTag();

        }

        private void renderDayHeaders(HtmlTextWriter output)
        {
            output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(HourNameBackColor));
            output.AddStyleAttribute("height", this.HeaderHeight + "px");
            output.RenderBeginTag("tr");

            foreach (Day d in days)
            {
                DateTime h = new DateTime(d.Start.Year, d.Start.Month, d.Start.Day, 0, 0, 0);

                // <td>
                output.AddAttribute("valign", "bottom");
                output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(HourNameBackColor));
                output.AddStyleAttribute("cursor", "default");
                output.AddStyleAttribute("border-right", "1px solid " + ColorTranslator.ToHtml(BorderColor));
                output.RenderBeginTag("td");

                // <div> block
//                DivWriter divBlock = new DivWriter();
                output.AddStyleAttribute("display", "block");
                output.AddStyleAttribute("border-bottom", "1px solid " + ColorTranslator.ToHtml(BorderColor));
                output.AddStyleAttribute("text-align", "center");
                output.RenderBeginTag("div");
//                output.Write(divBlock.BeginTag());

                // <div> text
//                DivWriter divText = new DivWriter();
                output.AddStyleAttribute("padding", "2px");
                output.AddStyleAttribute("font-family", DayFontFamily);
                output.AddStyleAttribute("font-size", DayFontSize);
                output.RenderBeginTag("div");
//                output.Write(divText.BeginTag());

                output.Write(h.ToString(this.headerDateFormat));
                //				output.Write("&nbsp;");

                output.RenderEndTag();
                output.RenderEndTag();
//                output.Write(divText.EndTag());
//                output.Write(divBlock.EndTag());
                output.RenderEndTag(); // </td>


            }

            output.RenderEndTag();
        }



        private void renderEventTds(HtmlTextWriter output)
        {

            int dayPctWidth = 100 / days.Length;

            for (int i = 0; i < days.Length; i++)
            {
                Day d = days[i];


                // <td>
                output.AddStyleAttribute("height", "1px");
                output.AddStyleAttribute("text-align", "left");
                output.AddAttribute("width", dayPctWidth + "%");
                output.RenderBeginTag("td");

                // <div> position
//                DivWriter divPosition = new DivWriter();
                output.AddStyleAttribute("display", "block");
                output.AddStyleAttribute("margin-right", ColumnMarginRight + "px"); 
                output.AddStyleAttribute("position", "relative");
                output.AddStyleAttribute("height", "1px");
                output.AddStyleAttribute("font-size", "1px");
                output.AddStyleAttribute("margin-top", "-1px");
                output.RenderBeginTag("div");
//                output.Write(divPosition.BeginTag());

                foreach (Event e in d.events)
                {
                    renderEvent(output, e, d);
                }

                // </div> position
//                output.Write(divPosition.EndTag());
                output.RenderEndTag();

                // </td>
                output.RenderEndTag();
            }
        }

        private void renderEvent(HtmlTextWriter output, Event e, Day d)
        {
            string displayText = e.Name + " (" + e.Start.ToShortTimeString() + " - " + e.End.ToShortTimeString() + ")";

            // real box dimensions and position
            DateTime dayVisibleStart = new DateTime(d.Start.Year, d.Start.Month, d.Start.Day, visibleStart.Hour, 0, 0);
            DateTime realBoxStart = e.BoxStart < dayVisibleStart ? dayVisibleStart : e.BoxStart;

            DateTime dayVisibleEnd;
            if (visibleEnd.Day == 1)
                dayVisibleEnd = new DateTime(d.Start.Year, d.Start.Month, d.Start.Day, visibleEnd.Hour, 0, 0);
            else if (visibleEnd.Day == 2)
                dayVisibleEnd = new DateTime(d.Start.Year, d.Start.Month, d.Start.Day, visibleEnd.Hour, 0, 0).AddDays(1);
            else
                throw new ArgumentOutOfRangeException("Unexpected time for dayVisibleEnd.");

            DateTime realBoxEnd = e.BoxEnd > dayVisibleEnd ? dayVisibleEnd : e.BoxEnd;

            // top
            double top = (realBoxStart - dayVisibleStart).TotalHours * HourHeight + 1;
            if (ShowHeader)
                top += this.HeaderHeight;

            // height
            double height = ((realBoxEnd - realBoxStart).TotalHours * HourHeight - 2);

            // It's outside of visible area (for NonBusinessHours set to Hide).
            // Don't draw it in that case.
            if (height <= 0)
            {
                return;
            }

            // MAIN BOX
            output.AddAttribute("onselectstart", "return false;"); // prevent text selection in IE

            if (EventClickHandling == UserActionHandling.PostBack)
            {
                output.AddAttribute("onclick", "javascript:event.cancelBubble=true;" + Page.ClientScript.GetPostBackEventReference(this, "PK:" + e.PK));
            }
            else
            {
                output.AddAttribute("onclick", "javascript:event.cancelBubble=true;" + String.Format(EventClickJavaScript, e.PK));
            }

            output.AddStyleAttribute("-moz-user-select", "none"); // prevent text selection in FF
            output.AddStyleAttribute("-khtml-user-select", "none"); // prevent text selection
            output.AddStyleAttribute("user-select", "none"); // prevent text selection
            output.AddStyleAttribute("cursor", "pointer");
            //output.AddStyleAttribute("cursor", "hand");
            output.AddStyleAttribute("position", "absolute");
            output.AddStyleAttribute("font-family", EventFontFamily);
            output.AddStyleAttribute("font-size", EventFontSize);
            output.AddStyleAttribute("white-space", "no-wrap");
            output.AddStyleAttribute("left", e.Column.StartsAtPct + "%");
            output.AddStyleAttribute("top", top + "px");
            output.AddStyleAttribute("width", e.Column.WidthPct + "%");
            output.AddStyleAttribute("height", (realBoxEnd - realBoxStart).TotalHours * HourHeight + "px");
            output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(EventBorderColor));
            output.RenderBeginTag("div");
            //output.Write(divMain.BeginTag());

            // FIX BOX - to fix the outer/inner box differences in Mozilla/IE (to create border)
//            DivWriter divFix = new DivWriter();
            output.AddAttribute("onmouseover", "this.style.backgroundColor='" + ColorTranslator.ToHtml(EventHoverColor) + "';event.cancelBubble=true;");
            output.AddAttribute("onmouseout", "this.style.backgroundColor='" + ColorTranslator.ToHtml(EventBackColor) + "';event.cancelBubble=true;");

            if (ShowToolTip)
            {
                output.AddAttribute("title", displayText);
            }

            output.AddStyleAttribute("margin-top", "1px");
            output.AddStyleAttribute("display", "block");
            output.AddStyleAttribute("height", height + "px");
            output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(EventBackColor));
            output.AddStyleAttribute("border-left", "1px solid " + ColorTranslator.ToHtml(EventBorderColor));
            output.AddStyleAttribute("border-right", "1px solid " + ColorTranslator.ToHtml(EventBorderColor));
            output.AddStyleAttribute("overflow", "hidden");
            output.RenderBeginTag("div");
//            output.Write(divFix.BeginTag());

            // blue column
            if (e.Start > realBoxStart)
            {
                
            }

            int startDelta = (int) Math.Floor((e.Start - realBoxStart).TotalHours * HourHeight);
            int endDelta = (int) Math.Floor((realBoxEnd - e.End).TotalHours * HourHeight);

//            DivWriter divBlue = new DivWriter();
            output.AddStyleAttribute("float", "left");
            output.AddStyleAttribute("width", "5px");
            output.AddStyleAttribute("height", height - startDelta - endDelta + "px");
            output.AddStyleAttribute("margin-top", startDelta + "px");
            output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(EventLeftBarColor));
            output.AddStyleAttribute("font-size", "1px");
            output.RenderBeginTag("div");
            output.RenderEndTag();
//            output.Write(divBlue.BeginTag());
//            output.Write(divBlue.EndTag());

            // right border of blue column
//            DivWriter divBorder = new DivWriter();
            output.AddStyleAttribute("float", "left");
            output.AddStyleAttribute("width", "1px");
            output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(EventBorderColor));
            output.AddStyleAttribute("height", "100%");
            output.RenderBeginTag("div");
            output.RenderEndTag();
//            output.Write(divBorder.BeginTag());
//            output.Write(divBorder.EndTag());

            // space
//            DivWriter divSpace = new DivWriter();
            output.AddStyleAttribute("float", "left");
            output.AddStyleAttribute("width", "2px");
            output.AddStyleAttribute("height", "100%");
            output.RenderBeginTag("div");
            output.RenderEndTag();
//            output.Write(divSpace.BeginTag());
//            output.Write(divSpace.EndTag());

            // PADDING BOX
//            DivWriter divPadding = new DivWriter();
            output.AddStyleAttribute("padding", "1px");
            output.RenderBeginTag("div");
//            output.Write(divPadding.BeginTag());

            output.Write(displayText); // e.BoxStart - dayVisibleStart

            // closing the PADDING BOX
            output.RenderEndTag();
//            output.Write(divPadding.EndTag());

            // closing the FIX BOX
            output.RenderEndTag();
//            output.Write(divFix.EndTag());

            // closing the MAIN BOX
//            output.Write(divMain.EndTag());
            output.RenderEndTag();
        }

        private void addHalfHourCells(HtmlTextWriter output, DateTime hour, bool hourStartsHere, bool isLast)
        {
            foreach (Day d in days)
            {
                DateTime h = new DateTime(d.Start.Year, d.Start.Month, d.Start.Day, hour.Hour, 0, 0);
                addHalfHourCell(output, h, hourStartsHere, isLast);
            }
        }

        private void addHalfHourCell(HtmlTextWriter output, DateTime hour, bool hourStartsHere, bool isLast)
        {
            string cellBgColor;
            if (hour.Hour < BusinessBeginsHour || hour.Hour >= BusinessEndsHour || hour.DayOfWeek == DayOfWeek.Saturday || hour.DayOfWeek == DayOfWeek.Sunday)
                cellBgColor = ColorTranslator.ToHtml(NonBusinessBackColor);
            else
                cellBgColor = ColorTranslator.ToHtml(BackColor);

            string borderBottomColor;
            if (hourStartsHere)
                borderBottomColor = ColorTranslator.ToHtml(HourHalfBorderColor);
            else
                borderBottomColor = ColorTranslator.ToHtml(HourBorderColor);

            DateTime startingTime = hour;
            if (!hourStartsHere)
                startingTime = hour.AddMinutes(30);

            if (FreetimeClickHandling == UserActionHandling.PostBack)
            {
                output.AddAttribute("onclick", "javascript:" + Page.ClientScript.GetPostBackEventReference(this, "TIME:" + startingTime.ToString("s")));
            }
            else
            {
                output.AddAttribute("onclick", "javascript:" + String.Format(FreeTimeClickJavaScript, startingTime.ToString("s")));
            }
            output.AddAttribute("onmouseover", "this.style.backgroundColor='" + ColorTranslator.ToHtml(HoverColor) + "';");
            output.AddAttribute("onmouseout", "this.style.backgroundColor='" + cellBgColor + "';");
            output.AddAttribute("valign", "bottom");
            output.AddStyleAttribute("background-color", cellBgColor);
            output.AddStyleAttribute("cursor", "pointer");
            output.AddStyleAttribute("cursor", "hand");
            output.AddStyleAttribute("border-right", "1px solid " + ColorTranslator.ToHtml(BorderColor));
            output.AddStyleAttribute("height", (HourHeight / 2) + "px");
            output.RenderBeginTag("td");

            // FIX BOX - to fix the outer/inner box differences in Mozilla/IE (to create border)
//            DivWriter divFix = new DivWriter();
            output.AddStyleAttribute("display", "block");
            output.AddStyleAttribute("height", "14px");
            if (!isLast)
                output.AddStyleAttribute("border-bottom", "1px solid " + borderBottomColor);
            output.RenderBeginTag("div");
//            output.Write(divFix.BeginTag());

            // required
            output.Write("<span style='font-size:1px'>&nbsp;</span>");

            // closing the FIX BOX
            output.RenderEndTag();
//            output.Write(divFix.EndTag());

            // </td>
            output.RenderEndTag();

        }


        #endregion

        #region Calculations


        /// <summary>
        /// This is only a relative time. The date part should be ignored.
        /// </summary>
        private DateTime visibleStart
        {
            get
            {
                DateTime date = new DateTime(1900, 1, 1);

                if (NonBusinessHours == NonBusinessHoursBehavior.Show)
                    return new DateTime(date.Year, date.Month, date.Day, 0, 0, 0);

                DateTime start = new DateTime(date.Year, date.Month, date.Day, BusinessBeginsHour, 0, 0);

                if (NonBusinessHours == NonBusinessHoursBehavior.Hide)
                    return start;

                if (days == null)
                    return start;

                if (totalEvents == 0)
                    return start;

                foreach (Day d in days)
                {
                    DateTime boxStart = new DateTime(date.Year, date.Month, date.Day, d.BoxStart.Hour, d.BoxStart.Minute, d.BoxStart.Second);
                    if (boxStart < start)
                        start = boxStart;
                }

                return new DateTime(start.Year, start.Month, start.Day, start.Hour, 0, 0);


            }
        }

        /// <summary>
        /// This is only a relative time. The date part should be ignored.
        /// </summary>
        private DateTime visibleEnd
        {
            get
            {
                DateTime date = new DateTime(1900, 1, 1);

                if (NonBusinessHours == NonBusinessHoursBehavior.Show)
                    return new DateTime(date.Year, date.Month, date.Day, 0, 0, 0).AddDays(1);

                DateTime end;
                if (BusinessEndsHour == 24)
                    end = new DateTime(date.Year, date.Month, date.Day, 0, 0, 0).AddDays(1);
                else
                    end = new DateTime(date.Year, date.Month, date.Day, BusinessEndsHour, 0, 0);

                if (NonBusinessHours == NonBusinessHoursBehavior.Hide)
                    return end;

                if (days == null)
                    return end;

                if (totalEvents == 0)
                    return end;

                foreach (Day d in days)
                {

                    bool addDay = false;
                    if (d.BoxEnd > DateTime.MinValue && d.BoxEnd.AddDays(-1) >= d.Start)
                        addDay = true;

                    DateTime boxEnd = new DateTime(date.Year, date.Month, date.Day, d.BoxEnd.Hour, d.BoxEnd.Minute, d.BoxEnd.Second);

                    if (addDay)
                        boxEnd = boxEnd.AddDays(1);

                    if (boxEnd > end)
                        end = boxEnd;
                }

                if (end.Minute != 0)
                    end = end.AddHours(1);

                return new DateTime(end.Year, end.Month, end.Day, end.Hour, 0, 0);
            }
        }


        private int totalEvents
        {
            get
            {
                int ti = 0;
                foreach (Day d in days)
                    ti += d.events.Count;

                return ti;
            }
        }
        #endregion

        #region Data binding


        protected override void PerformSelect()
        {
            // Call OnDataBinding here if bound to a data source using the
            // DataSource property (instead of a DataSourceID), because the
            // databinding statement is evaluated before the call to GetData.       
            if (!IsBoundUsingDataSourceID)
            {
                this.OnDataBinding(EventArgs.Empty);
            }

            // The GetData method retrieves the DataSourceView object from  
            // the IDataSource associated with the data-bound control.            
            GetData().Select(CreateDataSourceSelectArguments(),
                this.OnDataSourceViewSelectCallback);

            // The PerformDataBinding method has completed.
            RequiresDataBinding = false;
            MarkAsDataBound();

            // Raise the DataBound event.
            OnDataBound(EventArgs.Empty);
        }

        private void OnDataSourceViewSelectCallback(IEnumerable retrievedData)
        {
            // Call OnDataBinding only if it has not already been 
            // called in the PerformSelect method.
            if (IsBoundUsingDataSourceID)
            {
                OnDataBinding(EventArgs.Empty);
            }
            // The PerformDataBinding method binds the data in the  
            // retrievedData collection to elements of the data-bound control.
            PerformDataBinding(retrievedData);
        }

        protected override void PerformDataBinding(IEnumerable retrievedData)
        {
            // don't load events in design mode
            if (DesignMode)
            {
                return;
            }

            base.PerformDataBinding(retrievedData);

            if (DataStartField == null || DataStartField == String.Empty)
                throw new NullReferenceException("DataStartField property must be specified.");

            if (DataEndField == null || DataEndField == String.Empty)
                throw new NullReferenceException("DataEndField property must be specified.");

            if (DataTextField == null || DataTextField == String.Empty)
                throw new NullReferenceException("DataTextField property must be specified.");

            if (DataValueField == null || DataValueField == String.Empty)
                throw new NullReferenceException("DataValueField property must be specified.");


            // Verify data exists.
            if (retrievedData != null)
            {
                items = new ArrayList();

                foreach (object dataItem in retrievedData)
                {

                    DateTime start = Convert.ToDateTime(DataBinder.GetPropertyValue(dataItem, DataStartField, null));
                    DateTime end = Convert.ToDateTime(DataBinder.GetPropertyValue(dataItem, DataEndField, null));
                    string name = Convert.ToString(DataBinder.GetPropertyValue(dataItem, DataTextField, null));
                    string pk = Convert.ToString(DataBinder.GetPropertyValue(dataItem, DataValueField, null));

                    items.Add(new Event(pk, start, end, name));

                }

                items.Sort(new EventComparer());

//                loadEventsToDays();
            }
        }

        private void loadEventsToDays()
        {

            if (EndDate < StartDate)
                throw new ArgumentException("EndDate must be equal to or greater than StartDate.");

            int dayCount = (int)(EndDate - StartDate).TotalDays + 1;
            days = new Day[dayCount];

            for (int i = 0; i < days.Length; i++)
            {
                days[i] = new Day(StartDate.AddDays(i));

                if (items != null)
                    days[i].Load(items);

            }
        }

        #endregion


    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0


Written By
Czech Republic Czech Republic
My open-source event calendar/scheduling web UI components:

DayPilot for JavaScript, Angular, React and Vue

Comments and Discussions