This is quite easy with MSChart and the ChartType RangeBar.
Here is an example:
To get this result you need to
- Add an MSChart control from the data toolbox
- Add the using clause:
using System.Windows.Forms.DataVisualization.Charting;
- Then you can style the chart..
- ..and maybe set a size limit
Here is the code for setting it up:
void setUpGantt(Chart chart)
{
chart.Series.Clear();
Series s = chart.Series.Add("gantt");
s.ChartType = SeriesChartType.RangeBar;
s.YValueType = ChartValueType.DateTime;
s.AxisLabel = "";
s.IsVisibleInLegend = false;
Axis ax = chart.ChartAreas[0].AxisX;
Axis ay = chart.ChartAreas[0].AxisY;
ax.MajorGrid.Enabled = false;
ax.MajorTickMark.Enabled = false;
ax.LabelStyle.Format = " ";
ax.Enabled = AxisEnabled.False;
ay.LabelStyle.Format = "HH:mm";
ay.MajorGrid.Enabled = false;
ay.MajorTickMark.Enabled = false;
ay.LineColor = chart.BackColor;
limitGantt(chart, "8:00", "17:00");
}
void limitGantt(Chart chart, string start, string end)
{
Axis ax = chart.ChartAreas[0].AxisX;
ax.Minimum = 0.5; // we have only one slot
ax.Maximum = 1.5; // the bar is centered on its value (1)
Axis ay = chart.ChartAreas[0].AxisY;
ay.Minimum = fromTimeString(start).ToOADate(); // we exclude all times..
ay.Maximum = fromTimeString(end).ToOADate(); // ..outside a given range
}
Note that I used time strings
for convenience. Of course you can change to using DateTimes
directly. For the conversion of a time string
to a DateTime
of the current day this function is used:
DateTime fromTimeString(string time)
{
var p = time.Split(':');
int sec = p.Length == 3 ? Convert.ToInt16(p[2]) : 0;
TimeSpan t = new TimeSpan(Convert.ToInt16(p[0]), Convert.ToInt16(p[1]), sec);
return DateTime.Today.Add(t);
}
Note that all the code is lacking any checks!
To add a task this method is used:
void addGanttTask(Series s, string start, string end, Color c, int slot )
{
DateTime start_ = fromTimeString(start);
DateTime end_ = fromTimeString(end);
int pt = s.Points.AddXY(slot, start_, end_);
s.Points[pt].Color = c;
}
Note that it contains both a Series and a 'slot'. The slots are used for the x-values, which in your case all are the same. But one can easily image a more comples planner with several bars for several resources, like various rooms or teams..
The Series parameter would allow to overlay a second series like you can see in this nice example from MSDN..
Here is how I filled the chart:
setUpGantt(chart1);
Series s = chart1.Series[0];
addGanttTask(s, "8:00", "17:00", Color.LimeGreen, 1);
addGanttTask(s, "9:00", "9:20", Color.DarkSlateBlue, 1);
addGanttTask(s, "11:00", "12:00", Color.DarkSlateBlue, 1);
addGanttTask(s, "13:00", "13:20", Color.DarkSlateBlue, 1);
Note that different ranges may overlap and might hide each other. In our example the green bar is added first and the others lie on top. In the MSDN example you see how the yellow bars are narrower to keep the bars under them visible. They belong to a 2nd series.
To change the bars' widths use
series.SetCustomProperty("PixelPointWidth", "15");