When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article

ASP ASP.NET ASP FAQs Message Board Feedback
 
Print this Page!
Published: Wednesday, December 16, 2009

Using Microsoft's Chart Controls In An ASP.NET Application: Enhancing Charts With Ajax

By Scott Mitchell


A Multipart Series on Microsoft's Chart Controls
A picture is worth a 1,000 words... This adage rings especially true when it comes to reporting. Charts summarize and illuminate patterns in data in a way that long tables of numbers simply cannot. The Microsoft Chart Controls are a free and encompassing set of charts for WinForms and ASP.NET applications. This article series explores how to use these Chart Controls in an ASP.NET application.

  • Getting Started - walks through getting started using the Chart Controls, from version requirements to downloading and installing the Chart Controls, to displaying a simple chart in an ASP.NET page.
  • Plotting Chart Data - examines the multitude of ways by which data can be plotted on a chart, from databinding to manually adding the points one at a time.
  • Rendering the Chart - the Chart Controls offer a variety of ways to render the chart data into an image. This article explores these options.
  • Sorting and Filtering Chart Data - this article shows how to programmatically sort and filter the chart's data prior to display.
  • Programmatically Generating Chart Images - learn how to programmatically create and alter the chart image file.
  • Creating Drill Down Reports - see how to build drill down reports using the Chart control.
  • Adding Statistical Formulas - learn how to add statistical formulas, such as mean, median, variance, and forecasts, to your charts.
  • Enhancing Charts With Ajax - improve the user experience for dynamic and interactive charts using Ajax.
  • Serializing Chart Data - see how to persist a chart's data and appearance to a persistent store.
  • Using the Chart Controls with ASP.NET MVC - learn how to display charts in an ASP.NET MVC application.
  • Exporting Charts - allow visitors to export charts as images and PDF files.
  • (Subscribe to this Article Series! )

    Introduction


    Charts are typically used to provide a static snapshot of data. The chart's underlying data might be based on various user inputs, but in the end the chart, once rendered, represents the end of the reporting workflow. However, other scenarios allow for a more interactive user experience. For example, in the Creating Drill Down Reports article we looked at how to configure the Chart control to allow the user to drill into a particular data point. Specifically, the demo contained a column chart showing the number of products in each category in the Northwind database. Clicking on a column whisked the user to a new page that details about the products in that category. Also, in certain situations the data populating the chart might be arriving from a sensor or some other source that is constantly being updated. In that case, we might want a real time chart whose data is periodically (and automatically) refreshed to show the latest data.

    Ajax is a set of related techniques used in websites to build more interactive and responsive applications. Microsoft's ASP.NET Ajax Framework offers developers both server- and client-side frameworks for developing Ajax-enabled applications. This article looks at how to use Ajax with the Microsoft Chart controls, focusing on two demos. In the first we'll create a drill down report with a column chart that shows the gross sales per month for a particular category and fiscal year. The user can click on a particular column in the chart to see the breakdown of sales per day in that month on the same page. This breakdown is displayed in an UpdatePanel, and clicking on a column in the chart triggers an asynchronous postback. The other demo looks at using the Timer control to render a real time chart.

    Read on to learn more!

    - continued -

    Displaying Drill Down Data On The Same Page


    The Microsoft Chart controls offer two techniques for building drill down reports:
    • By setting the Url property of the points in the chart, or
    • By setting the the Series' PostBackValue property and creating an event handler for the Chart's Click event.
    The Creating Drill Down Reports installment showed how to use the first approach. This approach is useful if you want to send the user to a different page to view the drill down results. Setting the Url property causes the Chart control to render not only an <img> element for the chart, but an image map, as well. An image map defines a set of regions on the map through a series of coordinates and, in this case, associates a URL with each region. When the user clicks within a region, their browser sends them to the associated page.

    The second approach - setting the PostBackValue property and creating a server-side Click event handler - is similar to the first approach in that the Chart control renders an image map, but it differs in that when the user clicks on a region within the chart there is a postback. On postback the Chart control raises its Click event and the Click event handler executes. This second approach is useful for displaying drill down details on the same page.

    The download available for download at the end of the article includes a demo that allows the user to select a category and year from drop-down lists, and then shows the sales per month for the selected year and category in a column chart (see the screen shot below). This sales data chart is almost identical to the one we created in the Adding Statistical Formulas article, the only difference being that this chart is a column chart whereas the one in Adding Statistical Formulas was a line chart.

    Sales per month for Beverages in 1997.

    This chart allows the user to drill down into the sales for a particular month, showing the sales per day for the selected month. To show the monthly sales breakdown on the same page as the chart we need to configure the chart so that when a column is clicked there is a postback (rather than having the user whisked to a different page). By default, the Chart control is rendered as a static image. To make it interactive so that a postback occurs when a user clicks on a column we need to set the PostBackValue property. This property can be defined for a series and indicates value is sent back to the server on postback. If you need to know the Y value of the column that was clicked, set this property to #VALY. To get the X value use #VALX. You can pass both values back, separated by a comma, by setting the PostBackValue property to #VALX,#VALY.

    Displaying X and Y values as Tooltips
    The series that make up a chart can have a tooltip defined for each data point that can include the X and/or Y values using the same placeholders, #VALX and #VALY. What's more, you can use the syntax #VALX{formatSpecifier} or #VALY{formatSpecifier} to display the X or Y value in a tooltip based on the format specifier. For example, the ToolTip property defined in the series for this demo is Gross sales: #VALY{c}, which displays a tooltip with the text "Gross sales:" followed by the Y value formatted as a currency (as in, "Gross sales: $19,452.20").

    For this demo we need to know the X value of the selected column (the month whose sales data we want to drill into). Therefore, I've set the PostBackValue property to #VALX, as the following snippet of declarative markup shows:

    <asp:Chart ID="chtCategorySales" runat="server" ...>
       <Series>
          <asp:Series Name="SalesByMonth" ChartType="Column" BorderWidth="5"
             ToolTip="Gross sales: #VALY{c}"
             ChartArea="MainChartArea"
             YValueMembers="Total"
             XValueMember="Month"
             PostBackValue="#VALX" />
       </Series>
       
       <ChartAreas>
          ...
       </ChartAreas>
    </asp:Chart>

    With this simple addition, the Chart now renders with an image map and JavaScript necessary to cause a postback when a column in the chart is clicked. On postback, the Chart's Click event fires. We can respond to this event by creating a Click event handler.

    Protected Sub chtCategorySales_Click(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ImageMapEventArgs) Handles chtCategorySales.Click
       ...
    End Sub

    Note the second input parameter - it's of type ImageMapEventArgs. This type includes an e.PostBackValue property that contains the value specified by the PostBackValue property set in the series (the X value of the clicked column, in this case). So for our demo, e.PostBackValue contains a value between 1 and 12, which represents the month of the column that was clicked.

    The chtCategorySales_Click event handler is a bit long winded and is not central to the discussion of this article, so let me just describe its behavior in prose. The Click event handler starts by running a SQL query to get the sales per day for the selected month (via e.PostBackValue), year, and category. (The year and category are selected via a DropDownList control.) A Calendar control is used to highlight the days of the month based on the gross sales that day. If no sales were made that day then the day is not highlighted. If there were sales, the day is highlighted a color based on the sales. Specifically, there are five different colors, each representing a different quantity of sales.

    Confused yet? Don't worry, a screen shot will clarify things and make up for my less than clear description.

    The following screen shot was taken after clicking on the column in the chart corresponding to June. Clicking on that column (or any other one in the chart) causes a postback. On postback, the Chart's Click event handler runs and configures the legend and the Calendar based on the sales per day for that month / year / category. This drill down data gives the user a quick and meaningful grasp of how the sales for the selected month were dispersed. What's more, the user can hover her mouse over a day of the month to see the gross sales for that particular day.

    The drill down data breaks out the sales per day for June 1997.

    Enhancing the User Experience With An UpdatePanel


    Every time a user clicks one of the columns in the chart, a full page postback ensues. The browser re-requests the web page, sending the names and values of all of the form fields to the server. On the server, the page proceeds through its lifecycle and the entire HTML of the rendered page is returned to the browser, where it is displayed. This interaction is a bit unideal for a number of reasons, the key one being that only a small portion of the page is actually changed when clicking on a column, yet all of the page's markup is regenerated.

    Ajax helps mitigate this problem by reducing the information exchanged between the browser and the server and by seamlessly integrating the updated content into the page without needing to redraw the entire screen. As discussed in my multi-part series, Building Interactive User Interfaces with Microsoft ASP.NET AJAX, implementing Ajax techniques in an ASP.NET website is relatively easy thanks to the ASP.NET Ajax Framework.

    One of the major workhorses of this framework is the UpdatePanel, which is a server-side control that defines a region on the page that participates in partial page postbacks. In a nutshell, when an UpdatePanel needs to have its display refreshed, it uses JavaScript to make an asynchronous web request to the server. The web server re-renders the entire page, but only sends back the HTML for the UpdatePanel, thereby greatly reducing the amount of data exchanged. Back on the browser, the JavaScript that started the asynchronous page request seamlessly updates the UpdatePanel's markup once it is returned from the server. For more information on how the UpdatePanel works, along with demos illustrating how to use it, be sure to read Building Interactive User Interfaces with Microsoft ASP.NET AJAX: Using the UpdatePanel.

    We can enhance our demo to use Ajax by adding an UpdatePanel to the page and putting the Calendar and legend inside of it. Next, we need to tell the UpdatePanel to "refresh" itself whenever the user clicks one of the columns in the chart by adding an AsyncPostBackTrigger to the UpdatePanel. The following declarative markup (which is heavily abbreviated) shows the Chart, the UpdatePanel, the legend and the Calendar control. Note how the Chart is outside of the UpdatePanel - only the details that are displayed when clicking a column in the chart are part of the UpdatePanel. Also take note of the AsyncPostBackTrigger trigger in the UpdatePanel's declarative syntax. This AsyncPostBackTrigger says simply, "Trigger a partial page postback whenever the Chart's Click event fires."

    <asp:Chart ID="chtCategorySales" runat="server" ...>
       ...
    </asp:Chart>

    <asp:UpdatePanel runat="server" ID="udpDaySalesBreakdown">
       <ContentTemplate>
          <asp:Table ID="tblLegend" Caption="Legend" runat="server" ... />
          
          <asp:Calendar ID="calSalesPerDay" runat="server" ... />
       </ContentTemplate>
       <Triggers>
          <asp:AsyncPostBackTrigger ControlID="chtCategorySales" EventName="Click" />
       </Triggers>

    </asp:UpdatePanel>

    That's all there is to it! With the addition of an UpdatePanel and an AsyncPostBackTrigger, and by placing the Calendar and legend inside of the UpdatePanel, we now have a chart that we can drill into and that uses Ajax techniques to improve the user experience.

    Creating Real Time Charts


    The charts we have examined throughout this article series have all displayed static data whose values are not changing. For example, the charts showing the number of products per category or the sales per category per year are pulling data from a database and that data is (relatively) fixed. It's not like new sales data for 1997 is being added every couple of seconds, or new products are being added an existing category every minute of the day.

    But what if you need to chart data that is being updated in real time? Take Windows Task Manager, as an example. The Performance tab in Windows Task Manager shows CPU Usage History and Physical Memory Usage History as line charts being updated in real time. As each second (or so) passes, the chart is updated with the latest CPU and physical memory readings. In a business setting, you may be interested in tracking how many users are currently signed into your site, or the changing values for a particular stock quote.

    Creating such real time charts in a web application is challenging and carries some concerns around performance and scalability because in order for the chart to be updated the browser must make a request back to the server to get an updated chart image. The good news is that with Ajax you can have just the chart image refreshed (as needed) rather than reloading the entire page. The download available at the end of this article includes a demo of a real time chart that uses Ajax techniques and the ASP.NET Ajax Framework's Timer control to refresh the chart every 1.5 seconds.

    Specifically, the page contains a line chart inside of an UpdatePanel. The line chart's Y axis ranges from 0 to 100 and represents the reading from some fictional device or sensor. The X axis is used to record the time of the reading. The UpdatePanel also includes a Timer control whose Interval property is set to 1500. Consequently, every 1,500 milliseconds (or 1.5 seconds) the Timer will "tick," which invokes a postback. Because the Timer control is inside of the UpdatePanel, it actually causes a partial page postback instead of a full page postback.

    One very important part of creating such a real time chart is to set the Chart's EnableViewState property True. By default, this property is set to False, which means that points added to a series' Points collection are not remembered across postbacks. For a real time chart we need to have the Chart control remember these values so that on each "tick" we can add the latest value without having to worry about re-adding the previous ones.

    <asp:UpdatePanel ID="updRealtimeChart" runat="server">
       <ContentTemplate>
          <asp:Chart ID="chtRandomData" runat="server" Width="550px" Height="350px" EnableViewState="true">
             ...
          </asp:Chart>
          
          <asp:Timer ID="tmrRefreshChart" runat="server" Interval="1500" />
       </ContentTemplate>
    </asp:UpdatePanel>

    On the partial page postback, the Timer's Tick event is fired and the Tick event handler (if defined) will execute. The demo contains an event handler for this Tick event and in here we add a new point to the chart. The X value is the current time, the Y value is a randomly selected point that ranges between 5 "values" less than the previous point to 5 "values" more. (I use the word "values" here because we don't have a unit of measurement for the Y axis. If we were reading from a sensor that measured percentages, such as a CPU workload percentage, we would say that the randomly selected point ranges between 5 percentage points less to 5 percentage points more than the previous reading.)

    The following (abbreviated) code shows the logic used to add a random point to the chart when the Timer "ticks."

    Protected Sub tmrRefreshChart_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles tmrRefreshChart.Tick
       Dim rnd As New Random    'Used to generated random numbers

       'Get a reference to the Chart series
       Dim series As DataVisualization.Charting.Series = chtRandomData.Series("RandomSeries")

       'Have any points been added? If not, add one!
       If series.Points.Count = 0 Then
          'Start off with a point between 40 and 60, inclusive
          series.Points.AddXY(DateTime.Now.ToString("T"), rnd.Next(40, 61))
       End If

       'Compute the new Y value based on the last Y value
       Dim lastY As Double = series.Points(series.Points.Count - 1).YValues(0)
       Dim newY As Double = lastY + rnd.Next(-5, 6)

       'Add the point
       series.Points.AddXY(DateTime.Now.ToString("T"), newY)

       ...

    Here, series is a reference to the Chart's only series, which is what contains the data points that are plotted on the chart. If there are no points in the series' Points collection then an initial random point between 40 and 60 is added. Next, the previously-added points' Y value is determined and the next point's Y value is computed by taking the previous value and adding to it a number between -5 and 5. Finally, this new point is added to the Points collection using the AddXY method.

    As new points are added to the chart on every tick, we'll eventually run out of room on the right side of the chart. To remedy this we need to do two things:

    • Keep only the 100 most recently-added points (or the 50 most recent or 200 most recent or whatever you decide on...) , and
    • Adjust the X axis Minimum and Maximum values. This keeps the earliest added points to the far left of the axis and the just-added point on the far-right.
    In addition to these two steps, the demo also includes a stripe line to show the average value of the points displayed on the chart. (See Adding Statistical Formulas for more information on this topic.) Finally, the Chart's Title is updated to show the time of the most recent reading.

    The remainder of the Tick event handler follows.

       'If there are more than 100 points then remove points on the left until we get under 100
       While series.Points.Count > 100
          series.Points.RemoveAt(0)
       End While

       'Adjust X axis scale
       chtRandomData.ChartAreas("MainChartArea").AxisX.Minimum = series.Points(0).XValue
       chtRandomData.ChartAreas("MainChartArea").AxisX.Maximum = series.Points(0).XValue + 100

       'Determine the mean and display it
       Dim mean As Double = chtRandomData.DataManipulator.Statistics.Mean("RandomSeries")
       chtRandomData.ChartAreas("MainChartArea").AxisY.StripLines(0).IntervalOffset = mean

       'Update the title
       chtRandomData.Titles(0).Text = String.Format("Readings As Of {0:T}", DateTime.Now)
    End Sub

    The following screen shot shows the real time chart in action. The first one shows the chart after having collected about 50 readings (so after 90 seconds, or so). The second screen shot shows the real time chart several minutes later. Note how the data has filled the entire width of the X axis. As each new reading is made (that is, at every 1.5 seconds) a new point is added to the right, the left-most point is removed, and the X axis's Minimum and Maximum values are updated accordingly.

    The real time chart after about 60 readings.

    The real time chart after several minutes.

    Happy Programming!

  • By Scott Mitchell


    Attachments:

  • Download the code for this article
  • Further Reading


  • Using Microsoft's Chart Controls In An ASP.NET Application: Creating Drill Down Reports
  • Building Interactive User Interfaces with Microsoft ASP.NET AJAX
  • Building Interactive User Interfaces with Microsoft ASP.NET AJAX: Using the Timer Control
  • Building Interactive User Interfaces with Microsoft ASP.NET AJAX: Using the UpdatePanel


  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article