Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Chart Control: creare grafici professionali per ASP.NET con Visual Studio 2010

Creare grafici professionali per sfruttando i nuovi controlli di ASP.NET 4 e Visual Studio 2010
Creare grafici professionali per sfruttando i nuovi controlli di ASP.NET 4 e Visual Studio 2010
Link copiato negli appunti

Presentando le novità di ASP.NET 4.0 abbiamo evidenziato come il Chart Control sia stato finalmente integrato nel framework.

Partendo dalla toolbox di Visual Studio 2010 e trascinando il Chart Control nelle nostre pagine Web o nei nostri windows form possiamo costruire dei grafici altamente professionali con pochi semplici passi.

In questo articolo esaminiamo le caratteristiche principali del Chart Control e vediamo come usarlo all'interno di pagine Web. A tal fine realizziamo una semplice applicazione Web che presenta le statistiche di accesso di un blog con grafici a torta e a barre. L'applicazione sarà composta di due pagine. La prima pagina visualizza un grafico a torta che rappresenta il numero di articoli pubblicati nel blog raggruppati per categoria; ogni fetta della torta rappresenta quindi una categoria distinta.

Figura 1. Grafico a torta delle Categorie
Grafico a torta delle Categorie

Cliccando sulle fette del grafico a torta, l'utente accede alla seconda pagina della nostra applicazione, che contiene un grafico a barre. Questo secondo grafico mostra il dettaglio delle visite degli articoli appartenenti alla categoria selezionata.

Figura 2. Grafico a barre della categoria Informatica
Grafico a barre della categoria Informatica

In figura, l'articolo più letto della categoria Informatica è stato pubblicato il 06/12/2009 ed è stato letto 123 volte.

Aggiungere un grafico a torta

Cominciamo subito trascinando un Chart Control dalla casella degli strumenti di Visual Studio 2010 in una pagina Web. Questa operazione aggiunge del markup:

<%@ Register assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" namespace="System.Web.UI.DataVisualization.Charting" tagprefix="asp" %>
<asp:Chart ID="Chart1" runat="server">
  <Series>
    <asp:Series Name="Series1"></asp:Series>
  </Series>
  <ChartAreas>
    <asp:ChartArea Name="ChartArea1"></asp:ChartArea>
  </ChartAreas>
</asp:Chart>

Il Chart Control è identificato da un tag <asp:Chart>. Quando trasciniamo un Chart Control in una pagina il tag corrispondente viene automaticamente aggiunto al web.config:

<controls>
  <!-- ... -->
  <add tagPrefix="asp" namespace="System.Web.UI.DataVisualization.Charting"
       assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</controls>

Visual Studio 2010 fornisce un supporto completo per il Chart Control. L'impostazione delle caratteristiche è possibile direttamente dalla finestra delle proprietà, oltre che modificando il markup della pagina o intervenendo da codice.

La struttura di un grafico

Un elemento Chart è visualizzato all'interno di una pagina Web come una immagine singola e l'immagine può essere composta da più grafici. Ogni grafico è costituito da alcuni elementi:

Elemento Descrizione
Chart Area L'area rettangolare in cui viene disegnato il grafico
Series Gli elenchi di valori che vengono rappresentati.

  • I valori vengono descritti dalle coppie Point e DataPoint
  • Possiamo decidere la tipologia di grafico da assegnare alla serie (torta, barre, etc.)
  • Possiamo associare la serie ad una particolare Chart Area
Titoli e Legende Servono per aggiungere informazioni utili al grafico
Assi Sono gli assi di riferimento, anche questi possono avere i loro titoli
Figura 3. Elementi di un Chart Control
Elementi di un Chart Control

Associare i dati ad un grafico

Le Chart Area, le serie e i DataPoint possono essere specificati in maniera dichiarativa (attraverso l'uso del markup o attraverso la finestra delle proprietà) o per mezzo del codice.

Dati inseriti nel markup

Tipicamente le serie e le Chart Area sono specificate dichiarativamente mentre i Data Point sono popolati dinamicamente, grazie all'interrogazione di una base dati o ad altre fonti di dati. Cominciamo con il mostrare un grafico i cui dati sono tutti specificati dichiarativamente nel markup:

<asp:Chart ID="CategorieChart" runat="server">
 <Titles>
    <asp:Title Text="Articoli del Weblog raggruppati per Categoria">
 </asp:Title>
 </Titles>
 <series>
    <asp:Series Legend="Legend1" Name="CategorieSerie" YValueType="Int32" ChartType="Pie" IsValueShownAsLabel="True" ChartArea="AreaCategorie">
    <Points>
       <asp:DataPoint AxisLabel="Informatica" YValues="5" />
       <asp:DataPoint AxisLabel="Filosofia" YValues="1" />
       <asp:DataPoint AxisLabel="Poesia" YValues="4" />
     </Points>
   </asp:Series>
 </series>
 <chartareas>
   <asp:ChartArea Name="AreaCategorie">
       <Area3DStyle LightStyle="Realistic" Enable3D="true" />
    </asp:ChartArea>
 </chartareas>
 <Legends>
     <asp:Legend Name="Legend1" Title="Categorie">
     </asp:Legend>
 </Legends>
</asp:Chart>

Nella sezione Series è definita una sola serie che si chiama CategorieSerie. Questa serie verrà rappresentata in un grafico a torta visualizzato all'interno della Chart Area chiamata AreaCategorie. In questa Chart Area abbiamo indicato che il grafico deve essere tridimensionale impostando il tag Area3DStyle.

La serie Categorie è costituita da una collezione di Points. Ci sono 3 DataPoint che visualizzano sull'asse X del grafico il nome della categoria (proprietà AxisLabel) ed il numero di articoli appartenenti alla categoria sull'asse Y (proprietà YValues). Il grafico che si ottiene è quello che abbiamo visto in figura 1.

Dati inseriti da codice

Vediamo ora come specificare i Data Point da codice. Nel markup precedente eliminiamo la sezione Points perché inseriremo i valori nel sorgente:

protected void Page_Load(object sender, EventArgs e)
{
 if (!IsPostBack)
 {
   System.Web.UI.DataVisualization.Charting.Series SerieCategorie = CategorieChart.Series["CategorieSerie"];
   SerieCategorie.Points.AddXY("Informatica", 5);
   SerieCategorie.Points.AddXY("Filosofia", 1);
   SerieCategorie.Points.AddXY("Poesia", 4);
 }
}

Abbiamo definito una variabile SerieCategorie e la abbiamo associata alla serie CategorieSerie del nostro Chart. Abbiamo aggiunto i tre Data Point al Chart grazie al il metodo 'AddXY', esposto dalla collezione Points della serie.

In questo esempio abbiamo aggiunto a mano i 3 Data Point mentre è più plausibile che questi dati siano prelevati da una base dati o da una altra fonte.

Utilizzare un database

Il Chart control mette a disposizione una API con metodi che consentono di agganciare insiemi di dati alle serie del grafico con pochissime linee di codice. I metodi 'DataBindTable' e 'DataBindXY' permettono di associare alle serie del grafico, collezioni di dati che implementano l'interfaccia IEnumerable (ad esempio l'SqlDataReader).

Esaminiamo un frammento di codice che si connette ad un database Sql Server, esegue una query che ritorna le categorie di articoli e il numero di articoli per ogni categoria e aggancia il risultato al nostro Chart attraverso il metodo DataBindTable:

protected void Page_Load(object sender, EventArgs e)
{
  if (!IsPostBack)
  {
    SqlConnection conn = new SqlConnection();
    conn.ConnectionString = ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString;
    SqlCommand MyCommand = new SqlCommand();
    MyCommand.Connection = conn;
    MyCommand.CommandText = "SELECT Categoria, Articoli  FROM Categorie ORDER BY Categoria";
    conn.Open();
    SqlDataReader reader = MyCommand.ExecuteReader();
    CategorieChart.DataBindTable(reader, "Categoria");
    //CategorieChart.Series["CategorieSerie"].Points.DataBindXY(reader, "Categoria", reader, "Articoli");
  }
}

Il metodo 'DataBindTable' vuole come parametri di ingresso una collezione di dati enumerabili, il campo della collezione che alimenta l'asse X del grafico ed il campo della collezione che alimenta l'asse Y. Il metodo DataBindTable aggiunge dinamicamente un nuova serie al Chart quindi non è necessario definirla dichiarativamente nel markup. Se al posto del metodo DataBindTable si usa invece il metodo DataBindXY esposto dalla collection Points (vedi la linea di codice commentata nell'esempio precedente) è necessario definire la serie nel markup.

Per associare dati ad un grafico, possiamo usare anche la proprietà 'DataSource'. Questo implica il prelevare i dati da una sorgente, assegnarli al DataSource e chiamare infine il metodo DataBind del chart. Anche quando si usa il DataSource è necessario definire la serie coinvolta nel markup del Chart.

Ecco il codice:

SqlDataReader reader = MyCommand.ExecuteReader();
CategorieChart.Series["SerieCategorie"].XValueMember = "Categoria";
CategorieChart.Series["SerieCategorie"].YValueMembers = "Articoli";
CategorieChart.DataSource = reader;
CategorieChart.DataBind();

La collezione di dati myReader è la stessa dell'esempio precedente, è necessario esplicitare il campo della collezione che alimenta l'asse X del grafico ed il campo della collezione che alimenta l'asse Y.

Abbiamo visto come si imposta la proprietà DataSource a runtime ma è anche possibile impostare la proprietà 'DataSourceID' a design-time.

<asp:Chart ID="CategorieChart" DataSourceID="sqlDataSourceCategorie" runat="server">
<Titles>
  <asp:Title Text="Articoli del Weblog raggruppati per Categoria"></asp:Title>
</Titles>
<series>
  <asp:Series Legend="Legend1" XValueMember="Categoria"
              YValueMembers="Articoli" Name="CategorieSerie" YValueType="Int32"
              ChartType="Pie" IsValueShownAsLabel="True" ChartArea="AreaCategorie">
  </asp:Series>
</series>
<chartareas>
  <asp:ChartArea Name="AreaCategorie">
    <Area3DStyle LightStyle="Realistic" Enable3D="true" />
  </asp:ChartArea>
</chartareas>
<Legends>
  <asp:Legend Name="Legend1" Title="Categorie"></asp:Legend>
</Legends>
</asp:Chart>
<asp:SqlDataSource runat="server"  id="sqlDataSourceCategorie"
                   ConnectionString="<%$ ConnectionStrings:ApplicationServices %>"
                   SelectCommand="SELECT [Categoria], [Articoli] FROM [Categorie]" />

In questo caso abbiamo usato la proprietà DataSourceID del client per indicargli staticamente quale sorgente dati usare ovvero l'SqlDataSourceCategorie ed abbiamo impostato le proprietà XValueMember e YValueMember rispettivamente ai campi Categoria ed Articoli.

Creare grafici prelevando i dati da XML

Finora abbiamo visto come prelevare i dati da una base dati ma è possible prelevare dati da qualsiasi sorgente gestita da ADO.NET come ad esempio documenti XML, fogli Excel, file CSV, ecc. Questi dati vengono messi in oggetti DataReader, DataTable, DataSet e quindi agganciati al Chart con uno dei metodi proposti precedentemente.

La nostra applicazione Web prende i dati da file XML, proponiamo di seguito il file XML che contiene le categorie degli articoli:

<?xml version="1.0" encoding="utf-8"?>
<categorie>
  <categoria>
    <id_categoria>1</id_categoria>
    <descrizione>Informatica</descrizione>
    <articoli>5</articoli>
  </categoria>
  <!-- ... -->
</categorie>

Per accedere il file XML e leggere i dati in esso contenuti usiamo le API LINQ to XML:

XElement categorie = XElement.Load(Server.MapPath("~/App_Data/categorie.xml"));
foreach (XElement node in categorie.Elements("categoria"))
{
  string id_categoria = node.Element("id_categoria").Value;
  string categoria = node.Element("descrizione").Value;
  string articoli = node.Element("articoli").Value;
  CategorieChart.Series["CategorieSerie"].Points.AddXY(categoria, articoli);
  CategorieChart.Series["CategorieSerie"].MapAreaAttributes = "target="_blank"";
  //recupero il datapoint appena inserito e vi aggiungo le proprietà url e tooltip
  System.Web.UI.DataVisualization.Charting.DataPoint dp = new System.Web.UI.DataVisualization.Charting.DataPoint();
  dp = CategorieChart.Series["CategorieSerie"].Points[CategorieChart.Series["CategorieSerie"].Points.Count - 1];
  dp.Url = "articoli.aspx?id_categoria=" + id_categoria;
  dp.ToolTip =categoria;
}

Questo codice si trova all'interno dell'evento Page_Load, legge i nodi categoria e sfrutta i campi descrizione ed articoli per alimentare la serie di dati del Chart.

Grazie alla proprietà URL dei Data Point possiamo associare ad ogni punto un indirizzo Web (una azione). In questo modo, quando un utente clicca su un punto, appoderà all'indirizzo che abbiamo specificato.

Nel nostro esempio usiamo la proprietà URL per puntare al grafico di dettaglio che si aprirà cliccando su una fetta del grafico a torta. Il campo id_categoria ci informa su quale categoria del grafico ha cliccato l'utente.

I Data Point hanno anche una proprietà 'ToolTip' che ci permette di mostrare un fumetto quando l'utente si sofferma su una fetta del grafico a torta. Nel tooltip possiamo aggiungere informazioni riepilogative come il nome della categoria, il numero totale di articoli che ne fanno parte e la relativa percentuale.

Generazione automatica dell'immagine

Il Chart Control viene rappresentato all'interno di una pagina web come una immagine singola. Tale immagine viene generata dinamicamente alla richiesta del browser. Se mandiamo in esecuzione la nostra applicazione ed esaminiamo il markup generato dal Chart Control, troviamo al suo posto proprio un elemento <img>:

<img id="CategorieChart" src="/ChartImg.axd?i=chart_60cad518fa084e22b9fb6bc74f5eb790_1.png&
amp;g=3c83c6b374e0428ba04238e5291f1829" alt="" style=";;border-;" />

Questa immagine può avere quattro formati (PNG, BMP, JPG, EMF) ed essere generata in tre modi:

  • in maniera persistente e salvata in una locazione del file system del web server
  • come immagine temporanea e salvata in memoria o in sessione o su file. In questo caso sarà gestita da un http handler chiamato ChartHttpHandler
  • il Chart Control può spedire l'immagine direttamente al browser in formato binario

In ogni caso il Chart Control genera un tag <img> il cui attributo src referenzia l'immagine.

Il Chart Control per default usa la tecnica con Http Handler quindi descriveremo questa e lasceremo al lettore l'approfondimento delle altre due tecniche sopra citate.

La prima cosa da notare è che quando trasciniamo il Chart Control nella pagina viene automaticamente aggiunto nel web.config (oltre al tag <chart>) il tag httpHandlers:

<httpHandlers>
  <add path="ChartImg.axd" verb="GET,HEAD,POST" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler,
       System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
       validate="false" />
</httpHandlers>

L'HTTP Handler chiamato ChartHttpHandler è mappato al file ChartImg.axd.

Questo file appare nell'attributo src dell'immagine del grafico, ciò significa che la richiesta viene gestita dal ChartHttpHandler, il quale genera l'immagine e fornisce al browser in formato binario. In questa porzione del web.config possiamo definire i dettagli della persistenza dell'immagine.

Creare un grafico composito

Abbiamo visto come aggiungere un Chart Control in una pagina, come associare i dati al grafico e come questo viene rappresentato nel browser. Esaminiamo ora la creazione di un DrillDown Report ovvero un grafico "figlio" che dettaglia un elemento selezionato in un grafico "padre".

Nel nostro esempio il grafico padre è il grafico a torta delle Categorie ed il figlio è il grafico a barre che dettaglia le visite degli articoli appartenenti alla categoria selezionata dall'utente nel grafico padre. Creiamo il grafico figlio con le stesse modalità viste per il grafico a torta:

<asp:Chart ID="ArticoliChart" runat="server">
  <Titles>
    <asp:Title Text="Dettaglio della Categoria"></asp:Title>
  </Titles>
  <series>
    <asp:Series Name="ArticoliSerie" YValueType="Int32"
                ChartType="Column" IsValueShownAsLabel="True" >
    </asp:Series>
  </series>
  <chartareas>
    <asp:ChartArea Name="ChartArea1">
      <AxisY Title="Visite"></AxisY>
      <AxisX Title="Articoli"></AxisX>
    </asp:ChartArea>
  </chartareas>
</asp:Chart>

Ciò che ci consente di agganciare i due grafici è la proprietà Url del Chart Control.

Nel creare il grafico delle categorie, abbiamo impostato la proprietà Url all'indirizzo della pagina Web che contiene il grafico figlio, specificando la categoria con il campo id_categoria della querystring. In questo modo recuperiamo i dati di dettaglio della categoria scelta nel grafico padre.

Come per il grafico a torta, recuperiamo i dati da un file XML che presenta la seguente struttura:

<articoli>
  <articolo>
    <id_articolo>1</id_articolo>
    <id_categoria>1</id_categoria>
    <titolo>ASP.NET Routing: url amichevoli con Web Form 4.0 e Visual Studio 2010</titolo>
    <data>17/02/2010</data>
    <visite>54</visite>
    <url>http://simonemoretti75.wordpress.com/2010/02/17/asp-net-routing-url-amichevoli-con-web-form-4-0-e-visual-studio-2010/</url>
  </articolo>
  <!-- ... -->
<articoli>

e leggiamo i dati in esso contenuti usando le API LINQ to XML:

XElement articoli = XElement.Load(Server.MapPath("~/App_Data/articoli.xml"));
foreach (XElement node in articoli.Elements("articolo"))
{
  string id_categoria = node.Element("id_categoria").Value;
  string titolo = node.Element("titolo").Value;
  string data = node.Element("data").Value;
  string visite = node.Element("visite").Value;
  string url = node.Element("url").Value;
  if(id_categoria==Request.QueryString["id_categoria"])
  {
    ArticoliChart.Series["ArticoliSerie"].Points.AddXY(data, visite);
    ArticoliChart.Series["ArticoliSerie"].MapAreaAttributes = "target="_blank"";
    //recupero il datapoint appena inserito e vi aggiungo le proprietà url e tooltip
    System.Web.UI.DataVisualization.Charting.DataPoint dp = new System.Web.UI.DataVisualization.Charting.DataPoint();
    dp =ArticoliChart.Series["ArticoliSerie"].Points[ArticoliChart.Series["ArticoliSerie"].Points.Count - 1];
    dp.Url = url;
    dp.ToolTip = titolo;
  }
}

Il grafico che otteniamo è quello proposto in figura 2. Anche in questo caso abbiamo usato le proprietà URL e ToolTip. La prima la abbiamo impostata sull'indirizzo Web degli articoli e la seconda ci dice il titolo dell'articolo.

Conclusioni

Il framework .NET, dalla versione 4, ci mette a disposizione uno strumento molto potente pre la realizzazione di grafici dall'aspetto professionale. Il controllo è gratuito, facile da usare, flessibile, personalizzabile ed ampiamente integrato nel framework.

Ti consigliamo anche