New to Telerik UI for WinForms? Download free 30-day trial

Indicate Special Days in RadGanttView

Date Posted Product Author
February 09, 2015 RadGanttView for WinForms Hristo Merdjanov

Problem

By default, RadGanttView visualizes its items in rows, where all tasks are aligned according to the beginning and end time of each task. There is no clear column indication in the GraphicalViewElement.  This article demonstrates a sample approach how to achieve it.

Solution

We need to override the PaintElement method in the GanttViewGraphicalViewElement. For this purpose, we should also create a custom RadGanttView control containing a custom RadGanttViewElement.

indicate-special-days-in-radganttview001

Let`s first populate some data in our RadGanttView:

private void AddTasks()
{
    //Setup data items
    GanttViewDataItem item1 = new GanttViewDataItem();
    item1.Start = new DateTime(2014, 12, 15);
    item1.End = new DateTime(2014, 12, 20);
    item1.Progress = 30m;
    item1.Title = "Summary task.1. title";

    GanttViewDataItem subItem11 = new GanttViewDataItem();
    subItem11.Start = new DateTime(2014, 12, 16);
    subItem11.End = new DateTime(2014, 12, 18);
    subItem11.Progress = 10m;
    subItem11.Title = "Sub-task.1.1 title";

    GanttViewDataItem subItem12 = new GanttViewDataItem();
    subItem12.Start = new DateTime(2014, 12, 21);
    subItem12.End = new DateTime(2014, 12, 23);
    subItem12.Progress = 20m;
    subItem12.Title = "Sub-task.1.2 title";

    //Add subitems
    item1.Items.Add(subItem11);
    item1.Items.Add(subItem12);

    this.customRadGanttView.Items.Add(item1);

    GanttViewDataItem item2 = new GanttViewDataItem();
    item2.Start = new DateTime(2014, 12, 21);
    item2.End = new DateTime(2014, 12, 12);
    item2.Progress = 40m;
    item2.Title = "Summary task.2. title";

    GanttViewDataItem subitem21 = new GanttViewDataItem();
    subitem21.Start = new DateTime(2014, 12, 17);
    subitem21.End = new DateTime(2014, 12, 20);
    subitem21.Progress = 10m;
    subitem21.Title = "Sub-task.2.1 title";

    GanttViewDataItem subitem22 = new GanttViewDataItem();
    subitem22.Start = new DateTime(2014, 12, 21);
    subitem22.End = new DateTime(2014, 12, 23);
    subitem22.Progress = 30m;
    subitem22.Title = "Sub-task.2.2 title";

    GanttViewDataItem subitem23 = new GanttViewDataItem();
    subitem23.Start = new DateTime(2014, 12, 18);
    subitem23.End = new DateTime(2014, 12, 20);
    subitem23.Title = "Sub-task.2.3 title";

    //Add subitems
    item2.Items.Add(subitem21);
    item2.Items.Add(subitem22);
    item2.Items.Add(subitem23);

    this.customRadGanttView.Items.Add(item2);

    //Add links between items
    GanttViewLinkDataItem link1 = new GanttViewLinkDataItem();
    link1.StartItem = subItem11;
    link1.EndItem = subItem12;
    link1.LinkType = TasksLinkType.FinishToStart;
    this.customRadGanttView.Links.Add(link1);

    GanttViewLinkDataItem link2 = new GanttViewLinkDataItem();
    link2.StartItem = subitem21;
    link2.EndItem = subitem22;
    link2.LinkType = TasksLinkType.StartToStart;
    this.customRadGanttView.Links.Add(link2);

    GanttViewLinkDataItem link3 = new GanttViewLinkDataItem();
    link3.StartItem = subitem22;
    link3.EndItem = subitem23;
    link3.LinkType = TasksLinkType.FinishToStart;
    this.customRadGanttView.Links.Add(link3);

    GanttViewTextViewColumn titleColumn = new GanttViewTextViewColumn("Title");
    GanttViewTextViewColumn startColumn = new GanttViewTextViewColumn("Start");
    GanttViewTextViewColumn endColumn = new GanttViewTextViewColumn("End");

    this.customRadGanttView.GanttViewElement.Columns.Add(titleColumn);
    this.customRadGanttView.GanttViewElement.Columns.Add(startColumn);
    this.customRadGanttView.GanttViewElement.Columns.Add(endColumn);
}

Below is a screenshot of the control with its default look:

indicate-special-days-in-radganttview002

We can now start our own implementation of the CustomGanttViewGraphicalViewElement by inheriting the GanttViewGraphicalViewElement class. Following our business logic we should create a public property which will contain a list of the customized special days. In the PaintElement method override we are going to paint a vertical line for each date as well as a grey background for the weekends and an orange background for the special dates.

public class CustomGanttViewGraphicalViewElement : GanttViewGraphicalViewElement
{
    private List<DateTime> specialDates = new List<DateTime>();

    public CustomGanttViewGraphicalViewElement(RadGanttViewElement ganttView)
        : base(ganttView)
    { }

    public List<DateTime> SpecialDates
    {
        get { return specialDates; }
        set { specialDates = value; }
    }

    protected override Type ThemeEffectiveType
    {
        get { return typeof(GanttViewGraphicalViewElement); }
    }

    //Logic for painting the elements
    protected override void PaintElement(Telerik.WinControls.Paint.IGraphics graphics, float angle, System.Drawing.SizeF scale)
    {
        base.PaintElement(graphics, angle, scale);

        Rectangle clipRect = this.Bounds;
        Graphics g = graphics.UnderlayGraphics as Graphics;

        g.SetClip(clipRect);

        DateTime currentDate = this.TimelineBehavior.AdjustedTimelineStart;

        while (currentDate <= this.TimelineBehavior.AdjustedTimelineEnd)
        {
            float x = (float)((currentDate - this.TimelineBehavior.AdjustedTimelineStart).TotalSeconds / this.OnePixelTime.TotalSeconds);
            x -= this.HorizontalScrollBarElement.Value;
            float y = this.GanttViewElement.HeaderHeight;
            float y2 = this.Bounds.Height;

            if (currentDate.DayOfWeek == DayOfWeek.Saturday || currentDate.DayOfWeek == DayOfWeek.Sunday)
            {
                graphics.FillRectangle(new RectangleF(x, y, 100f, y2), Color.LightGray);
            }
            else if (this.SpecialDates.Contains(currentDate.Date))
            {
                graphics.FillRectangle(new RectangleF(x, y, 100f, y2), Color.Orange);
            }
            else
            {
                graphics.FillRectangle(new RectangleF(x, y, 100f, y2), Color.White);
            }

            graphics.DrawLine(Color.LightBlue, x, y, x, y2);

            currentDate = currentDate.AddDays(1);
        }

        g.ResetClip();
    }
}

Now, we are ready to substitute the GanttViewGraphicalViewElement in the RadGanttViewElement class. For the purpose we should make our own implementation and perform this operation:

public class CustomGanttViewElement : RadGanttViewElement
{
    protected override GanttViewGraphicalViewElement
CreateGraphicalViewElement(RadGanttViewElement ganttView)
    {
        return new CustomGanttViewGraphicalViewElement(this);
    }

    protected override Type ThemeEffectiveType
    {
        get { return typeof(RadGanttViewElement); }
    }
}

Going up in the hierarchy, now we should create our own RadGanttView control containing the already created in the previous step CustomGanttViewElement:

public class CustomGanttView : RadGanttView
{
    protected override RadGanttViewElement CreateGanttViewElement()
    {
        return new CustomGanttViewElement();
    }

    public override string ThemeClassName
    {
        get { return typeof(RadGanttView).FullName; }
    }
}

A complete solution in C# and VB.NET can be found here.

In this article