Cet article a fait l'objet d'une traduction automatique.
Extreme ASP.NET
Graphiques avec ASP.NET et LINQ
K. Scott Allen
Téléchargement de code disponible de la bibliothèque de code MSDN
Parcourir le code en ligne
Contenu
Mise en route
Création du graphique
Données de pompage
À partir de diagrammes de tableaux de bord
Graphiques l'avenir
Microsoft a récemment publié un nouveau contrôle graphique pour ASP.NET 3.5 Service Pack 1.Le contrôle graphique est facile à utiliser et vous permet d'ajouter visualisations données attrayante à vos applications Web ASP.NET.Le contrôle prend en charge toutes les types de graphique standard, comme les graphiques en courbes et les graphiques en secteurs, ainsi que visualisations avancées comme les graphiques entonnoir et pyramide.Dans cette chronique, je vais Explorez le contrôle de graphique et générer des données de l'utilisation des requêtes écrites pour LINQ aux objets.Le code source complet de cette colonne est disponible de la bibliothèque de code MSDN.
Figure 1 Visual Studio Tools
Mise en route
La première étape consiste àtélécharger le contrôle graphiqueà partir du Centre de téléchargement Microsoft.Ce téléchargement installe les composants runtime clé que vous aurez besoin pour les graphiques, y compris le sélection élective de l'assembly System.Web.DataVisualization dans le cache d'assembly global.
Vous devez également télécharger laSupport de Visual Studio 2008 outilet legraphique exemple de site Web. La prise en charge des outils vous donnera Intégration de la boîte à outils et de prise en charge IntelliSense au moment de la création, tandis que l'exemple de site Web vous donnera des centaines d'exemples pour examiner d'inspiration à la création du type de graphique souhaité.Notez que vous devez installé Visual Studio 2008 et runtime Microsoft .NET Framework 3.5 Service Pack 1.
Après que les installations sont tous les terminés, vous devez être en mesure de créer un nouveau projet ASP.NET dans Visual Studio et rechercher le contrôle graphique dans la fenêtre boîte à outils (voir figure 1 ).Vous pouvez faire glisser le graphique dans un fichier ASPX utilisant l'affichage Création (qui est des modifications de configuration nécessaires à votre fichier web.config) ou fonctionnent avec le contrôle directement dans la source Affichez d'un fichier ASPX (auquel cas vous devrez modifier manuellement la configuration je vais décrire bientôt).
Lorsque vous placez un graphique dans le concepteur de formulaires Web, Visual Studio place une nouvelle entrée dans la section <controls> de votre fichier web.config, comme suit :
<add tagPrefix="asp"
namespace="System.Web.UI.DataVisualization.Charting"
assembly="System.Web.DataVisualization,
Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
Cette entrée permet d'utiliser le contrôle graphique avec le préfixe balise familier asp qui utilisent d'autres contrôles ASP.NET intégrés. Visual Studio ajoute également une nouvelle entrée de gestionnaire HTTP dans la page IIS 7.0 <handlers> section et une entrée semblable dans la section <httphandlers> (pour une utilisation avec IIS 6.0 et le serveur de développement Web Visual Studio) :
<add name="ChartImageHandler"
preCondition="integratedMode"
verb="GET,HEAD"
path="ChartImg.axd"
type="System.Web.UI.DataVisualization.Charting.Chart HttpHandler,
System.Web.DataVisualization,
Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
Ce gestionnaire HTTP est responsable du traitement des demandes qui arrivent pour ChartImg.axd, le point final par défaut que le contrôle graphique utilisera pour traiter les graphiques. J'AI allons passer en plus de détails sur le gestionnaire HTTP ultérieurement. Le code dans la figure 2 indique les éléments de base d'un graphique. Chaque graphique comprend au moins un objet Series rempli avec des données. La propriété ChartType de chaque série détermine le type de graphique utilisé pour tracer la série (le type par défaut est un graphique en histogrammes). Chaque graphique peut également contenir un ou plusieurs objets ChartArea où le traçage est générée.
Figure 2 A base graphique
<asp:Chart ID="Chart1" runat="server" Height="300" Width="400">
<Series>
<asp:Series BorderColor="180, 26, 59, 105">
<Points>
<asp:DataPoint YValues="45" />
<asp:DataPoint YValues="34" />
<asp:DataPoint YValues="67" />
</Points>
</asp:Series>
</Series>
<ChartAreas>
<asp:ChartArea />
</ChartAreas>
</asp:Chart>
Vous pouvez personnaliser presque chaque élément visuel du contrôle graphique ASP.NET, notamment les arrière-plans, axes, titres, légendes et étiquettes. Le contrôle graphique est donc extrêmement personnalisable que vous devez avoir un plan dans emplacement dans lequel conserver les graphiques dans votre application aspect cohérent. Dans cette chronique, je vais utiliser une stratégie de générateur pour appliquer des polices cohérents et couleurs à tous les graphiques. Cette classe Générateur permet également l'utilisation du contrôle graphique en dehors des limites d'une page ASP.NET.
Création du graphique
Dans Recherchez des exemples de données à utiliser dans cette colonne, J'AI considérés comme brièvement utilisant des données historiques de marché boursier, mais les données de l'année passée a été depressing, donc plutôt que J'AI décidé d'utiliser les données des États-Unis bureau de transport statistiques (bts.gov). L'exemple d'application de cette colonne inclut un fichier contenant des informations sur chaque vol nationaux provenant de mon domicile aéroport (International Washington Marseille ou BWI) au cours de janvier de 2008. Les données incluent la ville de destination, distance, heures taxiing et délais. Ces données sont représentées dans C# via la classe dans la figure 3 .
La figure 3 Flight données
public class Flight {
public DateTime Date { get; set; }
public string Airline { get; set; }
public string Origin { get; set; }
public string Destination { get; set; }
public int TaxiOut { get; set; }
public int TaxiIn { get; set; }
public bool Cancelled { get; set; }
public int ArrivalDelay { get; set; }
public int AirTime { get; set; }
public int Distance { get; set; }
public int CarrierDelay { get; set; }
public int WeatherDelay { get; set; }
}
Le premier graphique J'AI créé à partir de cette données était un graphique pour afficher les plus populaires destinations des vols à partir de l'aéroport Marseille (voir figure 4 ). Ce graphique est créé en utilisant très peu de code dans le fichier ASPX ou son fichier de codebehind associé. Le fichier ASPX comprend un contrôle graphique sur la page, mais seulement définit les propriétés Largeur et hauteur, comme vous pouvez le voir :
<form id="form1" runat="server">
<div>
<asp:Chart runat="server" Width="800" Height="600" ID="_chart">
</asp:Chart>
</div>
</form>
La figure 4 destinations du haut (cliquez sur l'image pour l'agrandir)
Le codebehind délègue toutes ses événement Page_Load Gestion du travail à une classe TopDestinationsChartBuilder, comme vous le voyez ici :
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
var builder = new TopDestinationsChartBuilder(_chart);
builder.BuildChart();
}
}
Le TopDestinationsChartBuilder hérite d'une classe ChartBuilder. Cette classe de base ChartBuilder utilise un modèle de conception modèle méthode pour assembler les composants d'un graphique. La méthode modèle spécifie l'algorithme base nécessaire pour produire un graphique aesthetically cohérent et fonctionnel, mais fournit des accroches pour une sous-classe personnaliser les éléments assemblés. La méthode de modèle se nomme BuildChart et il est affiché dans la figure 5 .
La figure 5 BuildChart
public void BuildChart() {
_chart.ChartAreas.Add(BuildChartArea());
_chart.Titles.Add(BuildChartTitle());
if (_numberOfSeries > 1) {
_chart.Legends.Add(BuildChartLegend());
}
foreach (var series in BuildChartSeries()) {
_chart.Series.Add(series);
}
}
Chaque méthode Build de la classe ChartBuilder possède une méthode personnaliser associée. Une fois la méthode Build a créé son élément de graphique, il appelle la méthode personnaliser. Une classe dérivée pouvez remplacer la méthode de personnalisation pour appliquer les paramètres spécifiques de graphique. Un exemple est la méthode BuildChartTitle, illustrée figure 6 . La classe TopDestinationsChartBuilder remplace le CustomizeChartTitle pour appliquer le texte spécifique pour un titre :
protected override void CustomizeChartTitle(Title title)
{
title.Text = "Top Destinations";
}
La figure 6 BuildChartTitle
private Title BuildChartTitle() {
Title title = new Title() {
Docking = Docking.Top,
Font = new Font("Trebuchet MS", 18.0f, FontStyle.Bold),
};
CustomizeChartTitle(title);
return title;
}
protected virtual void CustomizeChartTitle(Title title) { }
La majorité du travail pour le TopDestinationsChartBuilder est conçue pour la personnalisation de la série du graphique, qui inclut l'ajout de tous les points de données pour l'affichage. Heureusement, est ridiculously facile à l'aide de LINQ to Objects, de rechercher les villes cinq destination d'une collection d'objets Flight comme vous pouvez le voir dans la figure 7 . Le code applique premier opérateur de GroupBy de LINQ pour regrouper les vols par leur Ville de destination. L'opérateur OrderByDescending trie ensuite la séquence des regroupements par le nombre de vols dans chaque groupe. Enfin, le code utilise l'opérateur requises pour identifier les destinations de cinq supérieure à partir de la souche.
Figure 7 Cities villes cinq Get haut
protected override void CustomizeChartSeries(IList<Series> seriesList) {
var repository = FlightRepositoryFactory.CreateRepository();
var query = repository.Flights
.GroupBy(flight => flight.Destination)
.OrderByDescending(group => group.Count())
.Take(5);
Series cities = seriesList.Single();
cities.Name = "Cities";
foreach (var record in query) {
cities.Points.AddXY(record.Key, record.Count());
}
}
La requête LINQ génère une séquence de regroupements. Vous pouvez exécuter une boucle dans ces regroupements pour ajouter des informations dans le graphique. La propriété clé de chaque groupe représente la valeur de la clé sélectionnée dans l'opérateur GroupBy (dans ce cas, la valeur de la ville de destination). Le code utilise la destination comme la valeur X de chaque point de données. Chaque groupe contient également une séquence énumérable des objets Flight qu'il regroupé sous cette destination. Vous devez utiliser l'opérateur nombre pour obtenir le nombre total de vols à chaque destination et ajoutez le compte en tant que la valeur Y de chaque point de données.
Données de pompage
Au lieu d'ajouter des données à un graphique série un point à la fois, vous pouvez utiliser une méthode DataBindXY sur DataPointCollection du graphique pour insérer une séquence de points de données sans en utilisant une boucle. Vous pouvez le voir se produire dans le DelaysByDayChartBuilder qui calcule le total de tous les retards (en minutes) pour chaque jour du mois. Ce Générateur génère également une seconde série de données affichant les retards liés à la météo total. Le Générateur commence par une requête LINQ qui regroupe les vols par jour du mois. La propriété de clé pour chaque regroupement maintenant représente le jour du mois (de 1 à 31 pour janvier) :
var query = repository.Flights
.GroupBy(flight => flight.Date.Day)
.OrderBy(group => group.Key)
.ToList();
Le code dans la figure 8 utilise la méthode DataBindXY. Tout d'abord, toutes les valeurs X sont regroupées dans une liste utilisant l'opérateur SELECT à récupérer la valeur de clé de chaque groupe. Traitement suivant, supplémentaire est appliqué à la requête initiale regroupement pour additionner les valeurs ArrivalDelay et WeatherDelay à l'intérieur de chaque groupe.
La figure 8 insérer valeurs sans Exécution d'une boucle
var xValues = query.Select(group => group.Key).ToList();
totalDelaySeries.Points.DataBindXY(
xValues,
query.Select(
group => group.Sum(
flight => flight.ArrivalDelay)).ToList());
weatherDelaySeries.Points.DataBindXY(
xValues,
query.Select(
group => group.Sum(
flight => flight.WeatherDelay)).ToList());
Comme vous pouvez le voir, les opérateurs LINQ standard facilitent le découper et manipuler les données des rapports graphiques. Un autre bon exemple est la TaxiTimeChartBuilder. Cette classe Assemble un graphique en radar pour afficher le délai total "taxi arrière » pour chaque jour de la semaine. Le temps « taxi hors » est le temps un avion entre en laissant la porte et la capture de la piste aéroport. Dans les aéroports encombrés l'heure "taxi des » pouvez soar comme plans file d'attente des et attendez que la piste effacer. Le TaxiTimeChartBuilder met en évidence les points de données où l'heure "taxi des » dépasse une valeur de seuil. Ce travail est effectué trivially facile utilisant une requête LINQ sur les points de données dans une série :
var overThresholdPoints =
taxiOutSeries.Points
.Where(p => p.YValues.First() > _taxiThreshold);
foreach (var point in overThresholdPoints)
{
point.Color = Color.Red;
}
Ici, modifier la couleur de chaque point de données qui dépasse le seuil spécifié est en rouge. Ce comportement peut devenir réfléchir à un rapport de tableau de bord aéroport, donc nous allons examiner les tableaux de bord ensuite.
À partir de diagrammes de tableaux de bord
Dans les cercles intelligence métier, tableaux de bord servent à afficher des informations clés sur une entreprise de façon graphique. Ces informations de performances peuvent provenir de diverses sources et visualiser l'aide d'une série de graphiques et des accessoires. Un utilisateur doit pouvoir Jetez un coup d'oeil à un affichage tableau de bord et d'identifier rapidement les anomalies qui peuvent affecter l'activité.
Un des défis en produisant un affichage tableau de bord est performances. Assemblage toutes les informations pour un tableau de bord peuvent entraîner une multitude de requêtes aux bases de données relationnelles et multidimensionnelles. Même lorsque les données brutes pour un tableau de bord sont mises en cache, le nombre de graphiques et d'accessoires à un tableau de bord pure pouvez burden un serveur.
la figure 9 illustre un simple tableau de bord pour un aéroport Affichage les destinations supérieure, taxi fois par jour de la semaine, vols total pour chaque jour de la semaine et le délai total pour chaque jour du mois. Une approche à la création de ce tableau de bord serait pour placer tous les contrôles de quatre graphique sur une page Web unique et utiliser les classes Générateur graphique nous avez création pour assembler les graphiques. Toutefois, imaginez que si chaque graphique nécessaire créer les deux secondes. Normalement, les deux secondes n'est pas beaucoup de temps attente d'une requête complexe, mais étant donné que j'un total de quatre graphiques sur la page (qui est un petit nombre d'un tableau de bord), l'utilisateur est en attente au moins huit secondes pour le premier graphique s'affiche.
La figure 9 aéroport activité Dashboard
Une approche différente à la création de cette page de tableau de bord consiste à définir espaces réservés pour chaque graphique dans la page et créer les images de graphique en mode asynchrone. Une approche asynchrone serait autoriser l'utilisateur à commencer à voir le premier résultat dès qu'il est disponible. Cette solution peut exploiter les proxys de Windows Communication Foundation (WCF) dans JavaScript pour afficher des graphiques dès qu'elles sont disponibles.
Heureusement, les classes Générateur que j'ai défini pour les graphiques facilitent déplacer la logique de génération graphique sous-jacente de services Web WCF. Le code dans la figure 10 montre une méthode de service WCF qui crée tout d'abord un graphique vide et crée ensuite une des classes dérivées de ChartBuilder implémentées dans le projet. Le générateur est spécifié comme paramètre à la méthode et le code vérifie ce paramètre sur une carte de générateurs connus pour rechercher le type réel de générateur pour instancier (à l'aide de Activator.CreateInstance).
La figure 10 instanciation un Générateur
[OperationContract]
public string GenerateChart(string builderName) {
Chart chart = new Chart() {
Width = 500, Height = 300
};
ChartBuilder builder =
Activator.CreateInstance(_typeMap[builderName], chart)
as ChartBuilder;
builder.BuildChart();
return SaveChart(builderName, chart);
}
L'aide d'une carte de types Générateur connus signifie que nous n'avons pas à transmettre à la méthode un nom de type réel et il fournit également une couche de l'isolation contre entrée malveillante à partir de sur Internet. Nous instancie uniquement le service sait à propos des types.
Production de l'image du graphique dans le service Web est difficile. Comme nous l'avons mentionné précédemment, le graphique fonctionne avec un gestionnaire HTTP pour afficher des graphiques sur le client. Plus précisément, le contrôle graphique fournit la classe ChartHttpHandler les octets représentant image terminé le graphique. Le ChartHttpHandler répond avec un identificateur unique. Lorsque le contrôle graphique affiche, il génère un standard HTML <img> balise avec l'attribut src référencement ChartImg.axd et notamment l'identificateur unique de la chaîne de requête. Lorsque cette demande image atteint le gestionnaire HTTP, le Gestionnaire de pouvez rechercher le graphique approprié pour l'affichage. Vous pouvez lire plus d'informations sur ce processus, comprenant toutes les options de configuration, dans Blog de Tchoparino delian.
Malheureusement, les API pour le gestionnaire HTTP ne sont pas publiques et donc ne sont pas disponibles dans un service Web. Au lieu de cela, la méthode SaveChart, dont le code de service dans la figure 10 appelle, utilise la méthode SaveImage du contrôle graphique pour écrire l'image du graphique dans le système de fichiers au format PNG. Le service renvoie ensuite le nom du fichier au client. En générant des fichiers physiques nous pouvez également présenter une stratégie de mise en cache et éviter les requêtes et la génération d'image pendant les périodes de surcharge.
Le code de la figure 11 utilise le service WCF à partir de JavaScript pour définir l'attribut src de l'espace réservé image chaque graphique. (Voir la colonne de Fritz Onion » Appels de service Web côté client avec extensions AJAX« Pour comprendre comment générer les proxys JavaScript et appeler les services Web avec JavaScript). Le document objet modèle (DOM document) identifiant et le Générateur de classe pour chaque graphique est définie dans un tableau de JavaScript qui fait partie d'un objet « contexte ». Ce contexte par est acheminée via les Web appels de service dans le paramètre userState des méthodes de proxy de service Web. JavaScript utilise l'objet de contexte pour suivre sa progression de la mise à jour les graphiques de tableau de bord. Pour les pages dynamiques tableau de bord, le serveur peut générer dynamiquement le tableau.
La figure 11 mise à jour le graphique
/// <reference name="MicrosoftAjax.js" />
function pageLoad() {
var context = {
index: 0,
client: new ChartingService(),
charts:
[
{ id: "topDestinations", builder: "TopDestinations" },
{ id: "taxiTime", builder: "TaxiTime" },
{ id: "dayOfWeek", builder: "DayOfWeek" },
{ id: "delaysByDay", builder: "DelaysByDay" }
]
};
context.client.GenerateChart(
context.charts[context.index].builder,
updateChart,
displayError,
context);
}
function updateChart(result, context) {
var img = $get(context.charts[context.index].id);
img.src = result;
context.index++;
if (context.index < context.charts.length) {
context.client.GenerateChart(
context.charts[context.index].builder,
updateChart, displayError, context);
}
}
function displayError() {
alert("There was an error creating the dashboard charts");
}
Graphiques l'avenir
J'ai abordé tout à fait un peu de technologie, notamment le modèle de conception de modèle méthode, opérateurs LINQ et services Web WCF compatible de JavaScript. Étant donné que cette colonne démontré une petite fraction de fonctionnalités disponibles dans le contrôle graphique, veillez Rechercher le site Web exemple pour voir la incroyable multitude de fonctionnalités disponibles. Combinaison de cet outil de visualisation très avec la flexibilité et expressiveness de LINQ signifie que vos futures applications graphiques sera plus flexible, efficace et utiles.
k. Scott Allen est membre du personnel technique Pluralsight et le fondateur de OdeToCode. Vous pouvez contacter Scott à Scott@OdeToCode.com ou lu son blog à odetocode.com/blogs/Scott.