Chart University - Chart 101 and Some 201 301 401 Stuff

Charts are fun and apparently useful.  They give people the ability to relate information quickly and effectively.  They show trends and patterns through the use of polygons in different locations and of varying sizes.  Most will probably agree with me on what I have said so far except for the fun part.  If you have ever tried to make your own chart, it is definitely not fun.  If you succeed, it will look primitive at best and unless you spent a great deal of resources to architect it to be easily extensible, any changes you require down the road will only add more code and bloat your custom control.  That is why using our UltraChart control, included in both NetAdvantage for Windows Forms or NetAdvantage for ASP.NET, will make your job much simpler and will impress stubborn crowds with minimal effort.

Where to start...

This post is going to show you the steps required to get familiar with our chart and will show some of the extensibility built into our UltraChart control.  Now, before I continue, I want to mention that anything I talk about here will apply to both WinChart and WebChart.  Since both are built on the same core code base, your WinChart code will affect your WebChart in the same manner and vice versa.  Also, I will use UltraChart to refer to both WinChart and WebChart.  A warning, this post is fairly long.  Even though this post shows the evolution of an UltraChart as we continue to add to it, you may jump around as each part does not depend on another.  Finally, it would be useful to bring in the following namespaces in your using statements:

using Infragistics.UltraChart.Core.Primitives;

using Infragistics.UltraChart.Resources.Appearance;

using Infragistics.UltraChart.Core;

ChartType

I usually learn by doing.  So let's do by dragging on a chart control onto your design surface.  One of the first properties you should get aquainted with is the ChartType property.  This property will dictate the type of chart that is shown to the user to visualize your data.  There are many different values for the ChartType enumeration, Line, Bar, Column, Funnel, Candle, Bubble, Treemap, Radar, Heat Map, Pie, Histogram, and Gantt to name some.  In addition, there are 3D and 2D variations to some of these charts.  For learning purposes, I am going to pick the 2D Column Chart.  Complete list here for 2D and 3D.

chartstep0

Data.DataSource

So, we know how we want to visualize the data.  But what good is a chart if it has nothing to plot?  There are many ways to provide the UltraChart data.  You can use an array, class derived from CollectionBase, DataSet, DataView, DataTable, IBindingList, IList, XML file, or Series object.  We are going to use a DataTable in this sample, but you can click on any of the above types to go to a help article that walks you through  consuming the other types of data sources. 

Another step completed.  We know where we are going to get the data from and which ChartType will render that data.  But, we do not know what kind of arrangement of data or the datatypes the chart expects.  This brings us to..

Chart Data Requirements

Here are the requirements for 2D and 3D charts.  You will see that there are various requirements for each chart type.  Some are more demanding than others.  And it's a good thing the Column chart is not one of those demanding types as it only requires one numeric column.  So let's create a DataTable with one numeric column.  We should be good to go, right?  Yes, if you want a chart to render.  No, if you want to render in a specific way.  By saying no, I am not talking about little tweaks to make the chart to look perfect, but instead you not only need to know what kind of data is necessary but how the UltraChart will interpret that data.  In the "ChartTypes" section of the documentation, there are "Working with (insert ChartType here) Data" articles under each ChartType.  These articles will give you a sample DataTable and a rendered chart to show you how the data will be represented by that specific chart type.  Here's the article for the 2D Column Chart.  Based on that example, I created the DataTable shown below.

Code for my DataTable that I will be using:

DataTable dt = new DataTable();

dt.Columns.Add("Month", typeof(string));

dt.Columns.Add("Leads", typeof(int));

dt.Columns.Add("Sales", typeof(int));

dt.Rows.Add("January", 120, 50);

dt.Rows.Add("February", 90, 44);

dt.Rows.Add("March", 70, 22);

dt.Rows.Add("April", 66, 21);

dt.Rows.Add("May", 80, 42);

dt.Rows.Add("June", 85, 48);

ultraChart1.Data.DataSource = dt;

ultraChart1.Data.DataBind();

Here is what my Chart looks like:

image

Minor Customizations (201)

Now that you should be able to make a chart of any type, let's go into some minor customizations that each of those charts may require.

Custom Axis Range

By default, the axis will scale based on the lowest and highest values, 21 and 120 in this case.  If you wanted to set it to show from 0 to 200, you can do that by setting the RangeType to Custom, RangeMax to 200, and RangeMin to 0  on the Y axis.

ultraChart1.Axis.Y.RangeType = Infragistics.UltraChart.Shared.Styles.AxisRangeType.Custom;

ultraChart1.Axis.Y.RangeMax = 200;

ultraChart1.Axis.Y.RangeMin = 0;

Chart after modification:

image

ColorModel

There are many different ways to control the coloring scheme of chart elements.  To do so you want to modify the ColorModel.ModelStyle property to the setting you wish to use.  I am going to demonstrate the CustomLinear setting in this sample but you can see the other various ways to modify the appearance being used here.

ultraChart1.ColorModel.ModelStyle = Infragistics.UltraChart.Shared.Styles.ColorModels.CustomLinear;

ultraChart1.ColorModel.CustomPalette = new Color[]{Color.Orange, Color.Orchid, Color.PapayaWhip};

Chart after modification:

image

Legend

It really isn't too necessary in this sample.  But there are cases where a legend can make a chart much more readable.  To make use of a legend, simply set it to be visible and set its location like so:

ultraChart1.Legend.Visible = true;

ultraChart1.Legend.Location = Infragistics.UltraChart.Shared.Styles.LegendLocation.Bottom;

Chart after modification:

image

TitleTop

You may also want to give your chart a title and you can make use of our TitleTop, TitleBottom, TitleLeft, and TitleRight properties.  You will want to set the Visible property to true and the Text property for what you wish to display.

ultraChart1.TitleTop.Visible = true;

ultraChart1.TitleTop.Text = "Leads and Sales for Q1 and Q2 of 2008";

Chart after Modification:

image

Modifications that Require More than 3 Lines of Code (301)

There are also some modifications that are not as simple as flipping a property.  These require using some of the events of the UltraChart and some knowledge of elements that make up one of these charts.

Changing the Color of an Item Based on a Condition (2D only)

To change the color of an element, known as a Primitive in the UltraChart world, you want to handle the ChartDrawItem event.  In this event, you can check the properties and settings of the current primitive to see if you want to make any modifications.  Here are some common properties  and conditions you would look at:

  • e.HasData - if the Primitive being drawn is tied to any data
  • e.Primitive.Path - Path is a string that signifies where a element lies
    • Border.Title.Top is for the Primitive for TitleTop
    • Border.Title.Grid.Y is for something on the Y Axis
    • Border.Title.Legend is for something in the Legend
  • e.Primitive.Value - value associated with the given element, usually the data value for a bar or line
  • certain type of primitive - some types of primitives

      if (e.Primitive is Polyline)

      {

          //do this

      }

private void ultraChart1_ChartDrawItem(object sender, Infragistics.UltraChart.Shared.Events.ChartDrawItemEventArgs e)

{

    //try casting the current primitive

    //being drawn to a Box

    Box b = e.Primitive as Box;

    //if current primitive is not a

    //box, return

    if (b == null)

    {

        return;

    }

    //if path is null

    if (b.Path == null)

    {

        //if the value is below 30

        if ((double)b.Value < 30)

        {

            //change the fill and fillstopcolor to red

            //setting both since gradients are being used

            b.PE.Fill = Color.Red;

            b.PE.FillStopColor = Color.Red;

        }

    }

}

Chart after Modification:

image

Adding Text to the Bars/Columns/Points (2D only)

Charts can be used for getting a general feel for the data or getting exact figures.  If the latter is required, you would make use of a ChartTextAppearance object and add it to to the ChartText collection for that ChartType.  For a column chart, it would be chart.ColumnChart.ChartText.  For a line chart, it would be chart.LineChart.ChartText.

ChartTextAppearance cta = new ChartTextAppearance();

cta.Visible = true;

//-2 signifies all rows or all columns

cta.Row = -2;

cta.Column = -2;

ultraChart1.ColumnChart.ChartText.Add(cta);

 

Chart after Modification:

image

Adding Various Primitives to the Chart (2D only)

Sometimes you need to add extra elements that are not provided in the data source or even if the data was available, the chart would not interpret that extra information in the manner necessary.  To clarify, imagine if you needed to add a target line to your sales chart.  If this value was in your table, your column chart would try to make a column out of it as there is no way to specify that value as a target line.  Since this line is not directly related to your data, you would have to draw this line in yourself.  To do that, you would handle the FillSceneGraph event, create primitives and add them to the SceneGraph.

Code to add a red target line to a column chart:

private void ultraChart1_FillSceneGraph(object sender, Infragistics.UltraChart.Shared.Events.FillSceneGraphEventArgs e)

{

    //gets the X and Y axis

    IAdvanceAxis x = (IAdvanceAxis)e.Grid["X"];

    IAdvanceAxis y = (IAdvanceAxis)e.Grid["Y"];

    //checks if axis exist

    if (x != null)

    {

        //figures out the coordinate to draw

        //a line at y=100

        int target = 100;

        int yVal = (int)y.Map(target);

        //note: the x axis is a string axis

        //that means that 0 stands for the first

        //column and 50 stands for the 50th

        //column               

        int xStart = (int)x.Map(0);

        int xEnd = (int)x.Map(50);

        //creates the line primitive based

        //on the coordinates

        Line l = new Line(new Point(xStart, yVal), new Point(xEnd, yVal));

        //sets the color of the line

        l.PE.Stroke = Color.Red;

        //adds it to the scene

        e.SceneGraph.Add(l);

    }

}

Chart after Modification:

image 

Customizations that are Considered Advanced (401)

There are certain changes that are not necessarily difficult but take a few steps to complete.  I will go into a couple of them here.

Custom Labels

There are many areas of text in a chart, whether it is axis tickmark labels, series labels, items labels, chart text, or tooltips.  These can be configured to show different text based on a FormatString property off that object.  There are some tokens that you can make use of such as <DATA_VALUE> or <ITEM_LABEL> (complete list here) but they do not encompass other more complex scenarios.  That's where the IRenderLabel interface comes in.  It allows you to customize any of the text on a chart that is configurable via the FormatString property.

To implement this feature, you have to have a class that implements IRenderLabel.  This interface has one member, ToString, which will be responsible for returning the string you want displayed given the context being passed in.  In this method, you will have access to things like the value of the element you are setting the text for, the row and column the element corresponds to in your table, and even things like the item and series labels that correspond to the given element.  Using this information, which is passed in as a hashtable, you can determine your output string and simply return that string.  This string will then show up in your chart.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Infragistics.UltraChart.Resources;

namespace WinChart101

{

    class CustomToolTips:IRenderLabel

    {

        #region IRenderLabel Members

        public string ToString(System.Collections.Hashtable context)

        {

            return (string)context["ITEM_LABEL"] +": "+ ((double)context["DATA_VALUE"]).ToString("#")+ " Thousand";

        }

        #endregion

    }

}

Once you have your class set up, you have to hook it up to your chart.  You can do that by doing the following:

//Create a hash table. This table will be used to associate a

//IRenderLabel object with a particular format string

Hashtable myHashTable = new Hashtable();

//Add a custom label string.

//The first param is the string

//The second param is the IRenderLabel object which will translate the string into the text the user will see on the screen.

//Note that this example is only creating one custom label. You can create as many different custom labels as you want.

//For each custom label, create a seperate IRenderLabel class and

//add an entry to the hash table linking the custom label string to the renderer.

myHashTable.Add("MyLabel", new CustomToolTips());

//Attach the Hash table to the Chart

this.ultraChart1.LabelHash = myHashTable;

//Assign the custom label to the ToolTip

this.ultraChart1.Tooltips.Format = Infragistics.UltraChart.Shared.Styles.TooltipStyle.Custom;

this.ultraChart1.Tooltips.FormatString = "<MyLabel>";

old Chart Tooltips:

image

NEW Chart Tooltips:

image

Note: This could have been done just by using the following:

this.ultraChart1.Tooltips.Format = Infragistics.UltraChart.Shared.Styles.TooltipStyle.Custom;

this.ultraChart1.Tooltips.FormatString = "<ITEM_LABEL>: <DATA_VALUE:#> Thousand";

The above was to show how you can set your chart to use a class that implements IRenderLabel.  Typically, you would use this for when the context is not readily available, ie. when data is in another table.

Composite Charts (2D only)

Composite charts are comprised of various 2D chart layers placed either next to or overlapping each other.  Essentially, you can take a candle chart layer, representing the high and low prices, and a column chart layer,representing the volume, and place them on a single chart control making use of the CompositeChart ChartType.  To create one of these charts you would have to create the following:

  • ChartArea - canvas where charts are placed
  • AxisItem - represents the X or Y axis, requirements based on the ChartType of the ChartLayerAppearance
  • ChartLayerAppearance - represents the ChartType layer, ie ColumnChart or ScatterChart
  • Series - provides data to each layer, types of Series that should be used with various ChartTypes

One thing to note, when working with a composite chart you have to provide data through the use of Series objects.  Series objects are essentially just a single set of data, that can be bound or not bound.  To help visualize what it would represent, think of each line being a series object in a LineChart and the orange columns being one series while the purple columns being another series in my column chart example above.  Also, these Series objects can be used with all chart types, not just composite.

Since the code for creating these is quite long, I am not including any code for them here.  You can take a look at the walkthroughs in our documentation where there are complete articles on creating these charts through the wizard, designer, and code.

Examples of Composite Charts (pictures only)

Composite Chart w/ Composite Legend:

comp1

Multiple Y-Axis w/ Line Layers:

comp2

Area and Line Chart in Top Area w/ Spline and Spline Area Chart on Bottom Area:

comp3 

Pop Quiz!

"Huh?" Don't "huh" me.  What would a university be without pop quizzes? (that wasn't the pop quiz)

  1. How do you specify different icons for the scatter chart?
  2. How can I set up my chart to have drill down (where you can click on a chart element to get a chart with further detailed information)?
  3. How can I set up the chart to allow zooming/scaling?
  4. How to I get a chart into a PDF document?
  5. How can I use the chart to plot just one or two values effectively? (think gauges, like a thermometer)

Answers (no looking before attempting the questions!)

So, how'd you do?  Don't feel too bad if you didn't know any of the them. I really didn't cover any of those topics.  I just was showing you that there are lots more to charts and this post does not cover everything that has to do with chart.  If you come up with any more questions that you can't find the answer to after reviewing the documentation, community site, and knowledge base, make use of the resources you have available, our support team and the forums.  For the questions above, here are the answers. 

  1. Each ChartType has a different set of properties that affect it.  In the "ChartTypes" section of the documentation, there are "(insert ChartType here) - Specific Properties" articles under each ChartType.  For the ScatterChart, there is a Icon property that controls which icon is used.
  2. You can implement the IDrillDown interface.  Help articles that explains this here.
  3. Different answers for Win or Web
    1. Win - can be set for x, y or both

      ultraChart1.Axis.X.ScrollScale.Visible = true;

      ultraChart1.Axis.X.ScrollScale.Scale = .5;

    2. Web - must set at design time so that the control will copy over the necessary scrollbar images

      UltraChart1.EnableScrollBar = true;

  4. There is a RenderPdfFriendlyGraphics method that you would call passing in a graphics object off the pdf. (Note: Requires a reference to the Infragistics.Documents assembly)

      Report r = new Report();

      ultraChart1.RenderPdfFriendlyGraphics(r.AddSection().AddCanvas().CreateGraphics());

  5. Kind of a trick question, you could just give it that one value and it would plot just fine.  However, you are probably better off using a gauge.  There are three different variations, radial, linear, or digital.  Like the UltraChart, you can also layer different types of gauges on top of each other (think your car speedometer that has an odometer also).

Graduation Day

If you read and understood every topic in this post, you have enough information to make most of the charts you will need in your application.  Congratulations, you are now a graduate of Chart University.  You will not be getting a paper diploma nor a diploma at all for that matter, just charts that will effectively convey information without causing too much stress.

Windows Forms sample uses the following:

-Infragistics NetAdvantage 2008 Volume 2 CLR 2.0

-Visual Studio 2008

Minimum requirements:

-Infragistics NetAdvantage (various version depending on feature being used)

Get Windows Forms Sample here.

ASP.NET sample uses the following:

-Infragistics NetAdvantage 2008 Volume 2 CLR 3.5

-Visual Studio 2008

Minimum requirements:

-Infragistics NetAdvantage (various version depending on feature being used)

Get ASP.NET Sample here.


Comments  (20 )

3675510
on Thu, Mar 19 2009 3:12 PM

This is a GREAT post...why can't I see the pictures?  It would be better :)

I tried right clicking and saying show picture

zdelo
on Wed, Apr 1 2009 3:44 PM

good article, but We can't see the pictures!

[Infragistics] Sung Kim
on Wed, Apr 1 2009 4:00 PM

Thanks for the feedback.  I just manually fixed all pictures.  They should all come up.

zdelo
on Wed, Apr 1 2009 4:17 PM

Good article.

I am using a composite chart with two steplines.

I added an X axis of type Time, Y axis of type Numeric and add 2 instances of NumericTimeSeries.

Now I tri to apply the code of the section "Adding Various Primitives to the Chart (2D only)".

But I have a null value of e.Grid. Why?

Thank in advances.

[Infragistics] Sung Kim
on Thu, Apr 2 2009 11:44 AM

@zdelo

You have to access almost everything off of chart.CompositeChart when working with this type.

IAdvanceAxis x =

 (IAdvanceAxis)ultraChart1.CompositeChart.ChartLayers[0].ChartLayer.Grid["X"];

help.infragistics.com/.../Chart_Access_Axis_Inside_FillSceneGraph_Event_of_a_Composite_Chart.html

zdelo
on Thu, Apr 2 2009 1:27 PM

Thank you, it works.

Mike
on Sun, Apr 12 2009 6:46 PM

Excellent article. Thank you.

I added 'target' lines to my chart, using your example.

Now I need to add these lines (and their colors) to the Chart Legend. How can I do this?

Thanks!

[Infragistics] Sung Kim
on Mon, Apr 13 2009 3:20 PM

@oamike

You can either handle the FillSceneGraph event and add your own primitives to the legend region or if you are using a composite chart you could probably create a dummy layer and add it to the composite legend.

help.infragistics.com/.../Chart_Creating_a_Composite_Chart.html

Mike
on Tue, Apr 14 2009 5:37 PM

Can you provide an example of how to add primitives to the Legend region using FillSceneGraph?

much appreciated!

[Infragistics] Sung Kim
on Wed, Apr 15 2009 3:20 PM

@oamike

It is rather complicated since it would involve retrieving various box elements and figuring out where you have space.  I would recommend going the route of composite charts and adding the "fake" chart layer to the chart area so that it appears in your composite chart legend.  You can take a look at the link in my previous comment for making a composite chart.

[Infragistics] Sung Kim
on Tue, May 5 2009 4:35 PM

@Vipul

Thanks for your feedback. This feature has been requested several times before and is weighted relative to other features every release.

@gregb

I’m glad you found this helpful.  An ongoing initiatives we have is to add more how to content including articles and videos to our site (community.infragistics.com).  We’re also making it easier to find content, by making the entire site searchable.  Even still, there are going to be scenarios that aren’t covered in the documentation. We’re always looking to understand the various ways our products are being used, and this certainly highlights one.  For questions like this, you could always contact the Infragistics support team

[Infragistics] Sung Kim
on Wed, May 27 2009 9:45 AM

@ C.

I have only seen the red x in situations with session and session based deployment.  I would make sure that no other settings are set that may be causing this.  If you open a case with support they should be able to debug the situation for you.

@ Mathusudan

I believe that there is a chart.ColumnChart.ColumnSpacing property but that is probably not what you are looking for.  To do that you may have to set a margin on the x axis.  Since there will now be a gap between the y and x axis you will have to fill in that line using the FillSceneGraph event I mentioned above.

For the different colors, you can use the ColorModel that I mention above if you are going to keep it consistent (one color for one series, another color for another series).  If the color can vary for every coloumn, they you may want to use the ChartDrawItem event I talk about above.

Maritime Associates
on Sat, May 30 2009 1:23 AM

Hi i wnat to add different color to each column of the infragistic chart and the first columns to placed little away from the y-axis. Please contact my email if any solution for this kmathusudan@yahoo.com

jebinjc
on Thu, Jul 16 2009 10:57 AM

I am really new to infragistics but found this forum really interesting.

I have a problem. I was making a Gantt Chart. I made a GanttSeries and in that GanttSeries I made different GanttItem and in each GanttItem I added different GanttTimeEntry which made my Gantt Chart. Now my problem

When I click on a specific GanttTimeEntry I need to retrieve the Start time and End Time.

I know you can track the click event on OnChartDataClicked but the Primitive's will be blank or null. So I cannot get the data's of that GanttTimeEntry. Is there any other way to get this. Hope you understood my problem..

Thanks in Advance

[Infragistics] Sung Kim
on Fri, Jul 24 2009 4:38 PM

@jebinjc

The chart will actually sort the data and it become hard to track where it originally came from.  Provided you have unique ColumnLabels you could work off the e.ColumnLabel in the ChartDataClick event args and search your DataTable for the appropriate row.  If the text is repeated then you may have to do some parsing through our source code to see how we arrange the data internally so you can create a mapping.  I did something similar like this for the box treemap chart type.  If you need further help on this, I would recommend contacting our support department for a faster guaranteed response.

jebinjc
on Thu, Jul 30 2009 1:53 AM

Thanks Sung Kim for the reply, but I triggered it out. Please go through the following post

forums.infragistics.com/.../123590.aspx

Jebin

jebinjc
on Thu, Jul 30 2009 2:01 AM

Thanks a lot Sung Kim for the reply but I have solved it in my own way. Please go through my post in Infragistics forum

forums.infragistics.com/.../123590.aspx

Thanks

Govardhana Reddy
on Wed, Apr 7 2010 4:58 AM

Hi,very good article.

Is there any way to show the custom tooltips in $ or % formats,with out appending those symbols to the string.

[Infragistics] Sung Kim
on Wed, Apr 7 2010 9:52 AM

@govardhanareddy

You can either add the string to the format string before or after the token, ie. <DATA_VALUE>, or you can take care of it in the ToString method of the IRenderLabel implementation.

Govardhana Reddy
on Mon, Apr 12 2010 8:49 AM

Hi stuff,

Thanx fr ur reply.

I have below problems regarding charts in my dashboard application.

(1)My piechart labels are not wrapping up properly,if I bind with huge data.See the below link,where I posted this.

community.infragistics.com/.../39874.aspx

(2)If I mouse Hover on the charts on the dashboard,tooltips are not showing up immedialtly,but if I minimize and maximize the window,then if I mouse hover again..it is showing the tooltips.Is there is anyway to avoid this?

Please see the below link where I posted this issue.

community.infragistics.com/.../39887.aspx

Iam struggling with the above issues from the long back,and I didn't get how to proceed on these.

Add a Comment

Please Login or Register to add a comment.