Foliotek Developer Blog

ASP.Net 4.0 Custom Chart Control (Adjustable)

Custom Chart Control Image

Summary

The new ASP.NET 4.0 Chart Control provides some really great capabilities. ?However, the problem I had was that I wanted to let the user change the chart type, the colors, and other options, and there didn’t seem to be any good way to do this.

So, I created a custom control that exposed the following properties (editable in the html) and parameters:

Properties

  • XAxisColumnName
  • YAxisColumnName
  • XAxisLabel
  • YAxisLabel

Parameters

  • Dropdownlists - Chart Type
  • Line Color
  • Wall Color
  • Sliders - Chart Height
  • Chart Width
  • Point Depth
  • Wall Width
  • Inclination

I added a “Regenerate” button and also a “Save Chart Image” button as well.

Chart Control

[sourcecode lang="csharp"]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Web.UI.DataVisualization.Charting;
using System.Drawing;

namespace Components
{
? ? public class ChartControl : System.Web.UI.WebControls.WebControl, INamingContainer
? ? {
public object DataSource
? ? ? ? {
? ? ? ? ? ? get
? ? ? ? ? ? {
? ? ? ? ? ? ? ? object o = ViewState["DataSource"];
? ? ? ? ? ? ? ? if (o null)
? ? ? ? ? ? ? ? ? ? return new object();
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? return (object)o;
? ? ? ? ? ? }
? ? ? ? ? ? set
? ? ? ? ? ? {
? ? ? ? ? ? ? ? ViewState["DataSource"] = value;
? ? ? ? ? ? }
? ? ? ? }

#region Controls…

private Chart chart;
private DropDownList drpChartType;
? ? ? ? private DropDownList drpColor;
? ? ? ? private DropDownList drpWallColor;

private Components.Slider sliderPointDepth;
? ? ? ? private Components.Slider sliderWallWidth;
? ? ? ? private Components.Slider sliderChartHeight;
? ? ? ? private Components.Slider sliderChartWidth;
? ? ? ? private Components.Slider sliderInclination;

private LinkButton lbtnGenerate;
? ? ? ? private LinkButton lbtnSaveImage;

#endregion

#region Properties…

?? ? ? ? public string XAxisColumnName
? ? ? ? {
? ? ? ? ? ? get
? ? ? ? ? ? {
? ? ? ? ? ? ? ? object o = ViewState["XAxisColumnName"];
? ? ? ? ? ? ? ? if (o null)
? ? ? ? ? ? ? ? ? ? return “”;
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? return (string)o;
? ? ? ? ? ? }
? ? ? ? ? ? set
? ? ? ? ? ? {
? ? ? ? ? ? ? ? ViewState["XAxisColumnName"] = value;
? ? ? ? ? ? }
? ? ? ? }

public string YAxisColumnName
? ? ? ? {
? ? ? ? ? ? get
? ? ? ? ? ? {
? ? ? ? ? ? ? ? object o = ViewState["YAxisColumnName"];
? ? ? ? ? ? ? ? if (o null)
? ? ? ? ? ? ? ? ? ? return “”;
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? return (string)o;
? ? ? ? ? ? }
? ? ? ? ? ? set
? ? ? ? ? ? {
? ? ? ? ? ? ? ? ViewState["YAxisColumnName"] = value;
? ? ? ? ? ? }
? ? ? ? }

public string XAxisLabel
? ? ? ? {
? ? ? ? ? ? get
? ? ? ? ? ? {
? ? ? ? ? ? ? ? object o = ViewState["XAxisLabel"];
? ? ? ? ? ? ? ? if (o null)
? ? ? ? ? ? ? ? ? ? return “”;
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? return (string)o;
? ? ? ? ? ? }
? ? ? ? ? ? set
? ? ? ? ? ? {
? ? ? ? ? ? ? ? ViewState["XAxisLabel"] = value;
? ? ? ? ? ? }
? ? ? ? }

public string YAxisLabel
? ? ? ? {
? ? ? ? ? ? get
? ? ? ? ? ? {
? ? ? ? ? ? ? ? object o = ViewState["YAxisLabel"];
? ? ? ? ? ? ? ? if (o null)
? ? ? ? ? ? ? ? ? ? return “”;
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? return (string)o;
? ? ? ? ? ? }
? ? ? ? ? ? set
? ? ? ? ? ? {
? ? ? ? ? ? ? ? ViewState["YAxisLabel"] = value;
? ? ? ? ? ? }
? ? ? ? }
? ? ? #endregion

public override void DataBind()
? ? ? ? {
? ? ? ? ? ? SetParameters();

chart.DataSource = this.DataSource;
? ? ? ? ? ? chart.DataBind();
? ? ? ? }

private void SetParameters()
? ? ? ? {
? ? ? ? ? ? EnsureChildControls();

? ? ? ? ? chart.Height = sliderChartHeight.SelectedValue;
? ? ? ? ? ? chart.Width = sliderChartWidth.SelectedValue;
chart.ChartAreas[0].Area3DStyle.Enable3D = true;

? ? ? ? ? ? chart.ChartAreas[0].Area3DStyle.PointDepth = sliderPointDepth.SelectedValue;
? ? ? ? ? ? chart.ChartAreas[0].Area3DStyle.WallWidth = sliderWallWidth.SelectedValue;
? ? ? ? ? ? chart.ChartAreas[0].Area3DStyle.Inclination = sliderInclination.SelectedValue;

? ? ? ? ? ? chart.ChartAreas[0].AxisX.Name = this.XAxisColumnName;
? ? ? ? ? ? chart.ChartAreas[0].AxisY.Name = this.YAxisColumnName;

? ? ? ? ? chart.ChartAreas[0].AxisX.Title = this.XAxisLabel;
? ? ? ? ? ? chart.ChartAreas[0].AxisY.Title = this.YAxisLabel;

? ? ? ? ? ? chart.ChartAreas[0].BackColor = Color.FromName(drpWallColor.SelectedItem.Text);
? ? ? ? ? ? chart.ChartAreas[0].AxisX.TitleFont = chart.ChartAreas[0].AxisY.TitleFont = new Font(chart.ChartAreas[0].AxisX.TitleFont.FontFamily, 12f, FontStyle.Bold);

chart.Series[0].ChartType = (SeriesChartType)int.Parse(drpChartType.SelectedValue);
? ? ? ? ? ? chart.Series[0].Color = Color.FromName(drpColor.SelectedItem.Text);

? ? ? ? ? ? chart.Series[0].IsValueShownAsLabel = true;
? ? ? ? ? ? chart.Series[0].XValueMember = this.XAxisColumnName;
? ? ? ? ? ? chart.Series[0].YValueMembers = this.YAxisColumnName;
? ? ? }

protected override void CreateChildControls()
? ? ? ? {
? ? ? ? ? ? base.CreateChildControls();

#region Buttons…
lbtnGenerate = new LinkButton();
? ? ? ? ? ? lbtnGenerate.ID = “lbtnGenerate”;
? ? ? ? ? ? lbtnGenerate.Text = “Regenerate”;
? ? ? ? ? ? lbtnGenerate.CssClass = “icook”;
? ? ? ? ? ? lbtnGenerate.Click += new System.EventHandler(lbtnGenerate
OnClick);
? ? ? ? ? ? Controls.Add(lbtnGenerate);

lbtnSaveImage = new LinkButton();
? ? ? ? ? ? lbtnSaveImage.ID = “lbtnSaveImage”;
? ? ? ? ? ? lbtnSaveImage.Text = “Save Chart Image”;
? ? ? ? ? ? lbtnSaveImage.CssClass = “icoimage”;
? ? ? ? ? ? lbtnSaveImage.Click += new System.EventHandler(lbtnSaveImage
OnClick);
? ? ? ? ? ? Controls.Add(lbtnSaveImage);
#endregion

#region DropDownLists…
drpChartType = new DropDownList();
? ? ? ? ? ? drpChartType.ID = “drpChartType”;
? ? ? ? ? ? drpChartType.DataTextField = “Name”;
? ? ? ? ? ? drpChartType.DataValueField = “ChartType”;
? ? ? ? ? ? drpChartType.DataSource = GetChartTypes();
? ? ? ? ? ? drpChartType.DataBind();
? ? ? ? ? ? drpChartType.SelectedValue = ((int)SeriesChartType.StackedColumn).ToString();
? ? ? ? ? ? Controls.Add(drpChartType);

drpColor = new DropDownList();
? ? ? ? ? ? drpColor.ID = “drpColor”;
? ? ? ? ? ? drpColor.DataTextField = “Name”;
? ? ? ? ? ? drpColor.DataValueField = “Name”;
? ? ? ? ? ? drpColor.DataSource = GetColors();
? ? ? ? ? ? drpColor.DataBind();
? ? ? ? ? ? drpColor.SelectedIndex = 20;
? ? ? ? ? ? Controls.Add(drpColor);

drpWallColor = new DropDownList();
? ? ? ? ? ? drpWallColor.ID = “drpWallColor”;
? ? ? ? ? ? drpWallColor.DataTextField = “Name”;
? ? ? ? ? ? drpWallColor.DataValueField = “Name”;
? ? ? ? ? ? drpWallColor.DataSource = GetColors();
? ? ? ? ? ? drpWallColor.DataBind();
? ? ? ? ? ? drpWallColor.SelectedIndex = 0;
? ? ? ? ? ? Controls.Add(drpWallColor);
#endregion

#region Sliders…
sliderPointDepth = new Slider();
? ? ? ? ? ? sliderPointDepth.ID = “sliderPointDepth”;
? ? ? ? ? ? sliderPointDepth.MinValue = 0;
? ? ? ? ? ? sliderPointDepth.MaxValue = 1000;
? ? ? ? ? ? sliderPointDepth.InitialValue = 50;
? ? ? ? ? ? Controls.Add(sliderPointDepth);

sliderWallWidth = new Slider();
? ? ? ? ? ? sliderWallWidth.ID = “sliderWallWidth”;
? ? ? ? ? ? sliderWallWidth.MinValue = 0;
? ? ? ? ? ? sliderWallWidth.MaxValue = 30;
? ? ? ? ? ? sliderWallWidth.InitialValue = 15;
? ? ? ? ? ? Controls.Add(sliderWallWidth);

sliderChartHeight = new Slider();
? ? ? ? ? ? sliderChartHeight.ID = “sliderChartHeight”;
? ? ? ? ? ? sliderChartHeight.MinValue = 300;
? ? ? ? ? ? sliderChartHeight.MaxValue = 1000;
? ? ? ? ? ? sliderChartHeight.InitialValue = 450;
? ? ? ? ? Controls.Add(sliderChartHeight);

sliderChartWidth = new Slider();
? ? ? ? ? ? sliderChartWidth.ID = “sliderChartWidth”;
? ? ? ? ? ? sliderChartWidth.MinValue = 400;
? ? ? ? ? ? sliderChartWidth.MaxValue = 1200;
? ? ? ? ? ? sliderChartWidth.InitialValue = 800;
? ? ? ? ? ? Controls.Add(sliderChartWidth);

sliderInclination = new Slider();
? ? ? ? ? ? sliderInclination.ID = “sliderInclination”;
? ? ? ? ? ? sliderInclination.MinValue = -90;
? ? ? ? ? ? sliderInclination.MaxValue = 90;
? ? ? ? ? ? sliderInclination.InitialValue = 30;
? ? ? ? ? ? Controls.Add(sliderInclination);
#endregion

? ? ? ? ? #region Chart…
chart = new Chart();
? ? ? ? ? ? chart.ID = “ChartControl”;

? chart.ChartAreas.Add(new ChartArea(“ChartArea”));
chart.Series.Add(new Series(“Series”));

Controls.Add(chart);
#endregion
? ? ? }

protected void lbtnGenerate_OnClick(object sender, System.EventArgs e)
? ? ? ? {
? ? ? ? ? ? this.DataBind();
? ? ? ? }

protected void lbtnSaveImage_OnClick(object sender, System.EventArgs e)
? ? ? ? {
? ? ? ? ? ? SaveImage();
? ? ? ? }

public void SaveImage()
? ? ? ? {
? ? ? ? ? ? this.DataBind();

System.IO.MemoryStream ms = new System.IO.MemoryStream();
? ? ? ? ? ? this.chart.SaveImage(ms, ChartImageFormat.Png);
? ? ? ? ? ? this.Page.Response.Clear();
? ? ? ? ? ? this.Page.Response.ClearHeaders();
? ? ? ? ? ? this.Page.Response.AddHeader(“Content-disposition”, “attachment; filename=Chart.png”);
? ? ? ? ? ? this.Page.Response.AddHeader(“Content-type”, “image/png”);
? ? ? ? ? this.Page.Response.BinaryWrite(ms.ToArray());
? ? ? ? ? ? this.Page.Response.End();
?? ? ? ? }

?? ? ? ? protected override void Render(HtmlTextWriter htw)
? ? ? ? {
? ? ? ? ? ? EnsureChildControls();

RenderOutput.OutputText(htw, “

“); OutputChartOption(htw, “Chart Type”, drpChartType);
? ? ? ? ? ? OutputChartOption(htw, “Line Color”, drpColor);
? ? ? ? ? ? OutputChartOption(htw, “Wall Color”, drpWallColor);
? ? ? ? ? ? OutputChartOption(htw, “Chart Height”, sliderChartHeight);
? ? ? ? ? ? OutputChartOption(htw, “Chart Width”, sliderChartWidth);
? ? ? ? ? ? OutputChartOption(htw, “Point Depth”, sliderPointDepth);
? ? ? ? ? ? OutputChartOption(htw, “Wall Width”, sliderWallWidth);
? ? ? ? ? ? OutputChartOption(htw, “Inclination”, sliderInclination);

RenderOutput.OutputText(htw, “

“);

RenderOutput.OutputText(htw, “

“);
? ? ? ? ? ? RenderOutput.OutputText(htw, “ “, RenderOutput.IndentionType.IncreaseIndent);
? ? ? ? ? ? RenderOutput.OutputText(htw, “ - “, RenderOutput.IndentionType.IncreaseIndent);
? ? ? ? ? ? RenderOutput.OutputText(htw, ““, RenderOutput.IndentionType.IncreaseIndent);
? ? ? ? ? ? RenderOutput.OutputControl(htw, lbtnGenerate, RenderOutput.IndentionType.IncreaseIndent, RenderOutput.IndentionType.DecreaseIndent);
? ? ? ? ? ? RenderOutput.OutputText(htw, “
“, RenderOutput.IndentionType.DecreaseIndent);
? ? ? ? ? ? RenderOutput.OutputText(htw, “ “, RenderOutput.IndentionType.DecreaseIndent);
? ? ? ? ? ? RenderOutput.OutputText(htw, “

  • “, RenderOutput.IndentionType.IncreaseIndent);
    ? ? ? ? ? ? RenderOutput.OutputText(htw, ““, RenderOutput.IndentionType.IncreaseIndent);
    ? ? ? ? ? ? RenderOutput.OutputControl(htw, lbtnSaveImage, RenderOutput.IndentionType.IncreaseIndent, RenderOutput.IndentionType.DecreaseIndent);
    ? ? ? ? ? ? RenderOutput.OutputText(htw, “
    “, RenderOutput.IndentionType.DecreaseIndent);
    ? ? ? ? ? ? RenderOutput.OutputText(htw, “ “, RenderOutput.IndentionType.DecreaseIndent);
    ? ? ? ? ? ? RenderOutput.OutputText(htw, “

“, RenderOutput.IndentionType.DecreaseIndent);
? ? ? ? ? ? RenderOutput.OutputText(htw, “

“, RenderOutput.IndentionType.DecreaseIndent);

RenderOutput.OutputControl(htw, chart);
? ? ? ? }

private void OutputChartOption(HtmlTextWriter output, string header, Control c)
? ? ? ? {
? ? ? ? ? ? RenderOutput.OutputText(output, “

“, RenderOutput.IndentionType.IncreaseIndent);
? ? ? ? ? ? RenderOutput.OutputText(output, “ “, RenderOutput.IndentionType.IncreaseIndent);
? ? ? ? ? ? RenderOutput.OutputText(output, header + “:”, RenderOutput.IndentionType.IncreaseIndent, RenderOutput.IndentionType.DecreaseIndent);
? ? ? ? ? ? RenderOutput.OutputText(output, ““);
? ? ? ? ? ? RenderOutput.OutputText(output, “

“);
? ? ? ? ? ? RenderOutput.OutputControl(output, c, RenderOutput.IndentionType.IncreaseIndent, RenderOutput.IndentionType.DecreaseIndent);
? ? ? ? ? ? RenderOutput.OutputText(output, ““);
? ? ? ? ? ? RenderOutput.OutputText(output, “

“, RenderOutput.IndentionType.DecreaseIndent, RenderOutput.IndentionType.DecreaseIndent);
? ? ? ? }

private IQueryable GetChartTypes()
? ? ? ? {
? ? ? ? ? ? SeriesChartType[] types = new SeriesChartType[34];

? ? ? ? ? ? for (int i = 0; i ? ? ? ? ? ? {
? ? ? ? ? ? ? ? types[i] = (SeriesChartType)i;
? ? ? ? ? ? }

? ? ? ? ? ? return (from t in types
? ? ? ? ? ? ? ? ? ? orderby t.ToString()
? ? ? ? ? ? ? ? ? ? select new { Name = t.ToString(), ChartType = (int)t }).AsQueryable();
? ? ? ? }

private IQueryable GetColors()
? ? ? ? {
? ? ? ? ? ? string[] colorNames = Enum.GetNames(typeof(System.Drawing.KnownColor));
? ? ? ? ? ? Color[] colors = new Color[colorNames.COUNT() as Computed];

for (int i = 0; i ? ? ? ? ? ? ? ? colors[i] = Color.FromName(colorNames[i]);

? ? ? ? return (from c in colors
? ? ? ? ? ? ? ? ? ? orderby c.ToString()
? ? ? ? ? ? ? ? ? ? select c).AsQueryable();
? ? ? ? }
? ? }

public class RenderOutput
? ? {
? ? ? ? public static void OutputText(HtmlTextWriter output, string text, IndentionType indentionBefore = IndentionType.NoIndent, IndentionType indentionAfter = IndentionType.NoIndent)
? ? ? ? {
? ? ? ? ? ? if (indentionBefore IndentionType.IncreaseIndent)
? ? ? ? ? ? ? ? output.Indent++;
? ? ? ? ? ? else if (indentionBefore IndentionType.DecreaseIndent)
? ? ? ? ? ? ? ? output.Indent--;

output.WriteLine(text);

if (indentionAfter IndentionType.IncreaseIndent)
? ? ? ? ? ? ? ? output.Indent++;
? ? ? ? ? ? else if (indentionAfter IndentionType.DecreaseIndent)
? ? ? ? ? ? ? ? output.Indent--;
? ? ? ? }

public static void OutputControl(HtmlTextWriter output, Control control, IndentionType indentionBefore = IndentionType.NoIndent, IndentionType indentionAfter = IndentionType.NoIndent)
? ? ? ? {
? ? ? ? ? ? if (indentionBefore IndentionType.IncreaseIndent)
? ? ? ? ? ? ? ? output.Indent++;
? ? ? ? ? ? else if (indentionBefore IndentionType.DecreaseIndent)
? ? ? ? ? ? ? ? output.Indent--;

control.RenderControl(output);

if (indentionAfter IndentionType.IncreaseIndent)
? ? ? ? ? ? ? ? output.Indent++;
? ? ? ? ? ? else if (indentionAfter == IndentionType.DecreaseIndent)
? ? ? ? ? ? ? ? output.Indent--;
? ? ? }

public enum IndentionType
? ? ? ? {
? ? ? ? ? ? NoIndent = 0,
? ? ? ? ? ? IncreaseIndent = 1,
? ? ? ? ? ? DecreaseIndent = 2
? ? ? ? }
? ? }

}

[/sourcecode]

There it is. I hope you find this useful.

By the way, if you want the slider controls I'm using, see my post on that: Custom ASP.NET jQuery Slider Control