Dies sind maschinell übersetzte Inhalte, die von den Mitgliedern der Community bearbeitet werden können. Sie können die Übersetzung verbessern, indem Sie auf den jeweils zum Satz gehörenden Link "Bearbeiten" klicken.Mithilfe des Dropdown-Steuerelements "Inhalt anzeigen" links oben auf der Seite können Sie zudem bestimmen, ob nur der englische Originaltext, nur die deutsche Übersetzung oder beides nebeneinander angezeigt werden.
.NET Visualization
Visualizing Information with .NET
Laurence Moroney
This article discusses:
-
Data visualization
-
Building data-agnostic services
-
Building a visualization server
|
This article uses the following technologies:
C#, ASP.NET, XML
|

Contents
Information visualization has been around for a long time, but ask different people what it means, and you'll likely get many different answers—for example, charting, innovative animated images, or computationally intensive representations of complex data structures.
Information visualization encapsulates all of these answers, and an information visualization platform is one that can support each of these scenarios.
From a scientific perspective, information visualization is usually used to define the study of the visual representation of large-scale collections of information that is not necessarily numeric in nature, and the use of graphical representations of this data to allow the data to be analyzed and understood.
From a business perspective, information visualization is all about deriving value from data through graphical rendering of the data, using tools that allow end users to interact with the data to find the information that they need.
Of course, having just the capability to draw these pictures usually isn't enough for a good information visualization platform; there are also other levels of functionality that need to be addressed, such as:
-
Interactivity Interactivity can vary from animating the movement of slices in and out of a pie chart to providing users with tools for data manipulation, such as zooming in and out of a time series.
-
Generating related metadata Many charts have value added to them through related contextual metadata.
For example, when you view a time-series chart, you might want to generate a moving average and tweak the period for this moving average or experiment with what-if scenarios.
It's not feasible to expect a data source to generate all of these data views for you.
Some form of data manipulation is necessary at the presentation layer.
-
Overlaying related data A common requirement for charting is to take a look at other stimuli that might affect the data and have the visualization reflect this.
Consider a time series showing a company's stock value and a feed of news stories about that particular stock.
Real value can be added to the chart by showing how the news affected the value. "
Good" news might make it go up, "bad'" news might make it go down.
Being able to add this data to your time-series chart turns it from a simple chart into information visualization.
The key to building a visualization platform that can enable all of this is to have flexibility, so that you can render any data in any way at any time.
This is a huge and generally specialized effort, but a technique that you can use to ease this effort is to use with called data agnotisticism.
Data agnosticism arises when you define an architecture for visualizing your data that isn't dependent on the data itself.
For example, if you consider the example of a time-series chart that provides related metadata, it's quite easy to program an application to read the time-series data and the related metadata (such as a news feed) and to write the data on to the screen using a charting engine.
However, once you've done this, your effort is good for this representation and this representation alone.
The application you've written is tightly bound to the data itself.
The principle of data agnosticism allows you to pick a data source, define the data you want, and then tell the visualization engine to go and draw it however you want it to.
We'll take a look at how to build a simple version of this engine in this article.
Getting Started
As with anything else, it's good to start with the data.
In this section, I'll give a brief overview of a simple XML-over-HTTP service that provides time-series data provided by Yahoo Financial Services.
The Yahoo time-series service returns a CSV file containing basic time-series data with the following fields: Date, Opening Price, Closing Price, High, Low, Volume, and Adjusted Close.
The API to call it is very simple:
ichart.finance.yahoo.com/table.csv
You use the following parameters:
|
Figure 1 Size and Access Times with Non-local Storage
|
|
Parameter
|
Value
|
|
s
|
Stock Ticker (for example, MSFT)
|
|
a
|
Start Month (0-based; 0=January, 11=December)
|
|
b
|
Start Day
|
|
c
|
Start Year
|
|
d
|
End Month (0-based; 0=January, 11=December)
|
|
e
|
End Day
|
|
f
|
End Year
|
|
g
|
Always use the letter d
|
|
ignore
|
Always use the value '.csv'
|
To get the time-series data for Microsoft (MSFT) from January 1, 2008, to January 1, 2009, you use the following URL:
Figure 1 shows a C# function that takes string parameters for ticker, start date, and end date and builds this URI.

Figure 1 A C# Function That Builds a URI to Capture Data
public string BuildYahooURI(string strTicker,
string strStartDate, string strEndDate)
{
string strReturn = "";
DateTime dStart = Convert.ToDateTime(strStartDate);
DateTime dEnd = Convert.ToDateTime(strEndDate);
string sStartDay = dStart.Day.ToString();
string sStartMonth = (dStart.Month -1).ToString();
string sStartYear = dStart.Year.ToString();
string sEndDay = dEnd.Day.ToString();
string sEndMonth = (dEnd.Month - 1).ToString();
string sEndYear = dEnd.Year.ToString();
StringBuilder sYahooURI =
new StringBuilder("http://ichart.finance.yahoo.com/table.csv?s=");
sYahooURI.Append(strTicker);
sYahooURI.Append("&a=");
sYahooURI.Append(sStartMonth);
sYahooURI.Append("&b=");
sYahooURI.Append(sStartDay);
sYahooURI.Append("&c=");
sYahooURI.Append(sStartYear);
sYahooURI.Append("&d=");
sYahooURI.Append(sEndMonth);
sYahooURI.Append("&e=");
sYahooURI.Append(sEndDay);
sYahooURI.Append("&f=");
sYahooURI.Append(sEndYear);
sYahooURI.Append("&g=d");
sYahooURI.Append("&ignore=.csv");
strReturn = sYahooURI.ToString();
return strReturn;
}
Now that you have the URI for the data, you need to read it and to use it.
In this case, I'll convert the CSV data to XML.
A function that can do this is shown in Figure 2.

Figure 2 Converting CSV Data to XML
public XmlDocument getXML(string strTicker,
string strStartDate, string strEndDate)
{
XmlDocument xReturn = new XmlDocument();
DataSet result = new DataSet();
string sYahooURI =
BuildYahooURI(strTicker, strStartDate, strEndDate);
WebClient wc = new WebClient();
Stream yData = wc.OpenRead(sYahooURI);
result = GenerateDataSet(yData);
StringWriter stringWriter = new StringWriter();
XmlTextWriter xmlTextwriter = new XmlTextWriter(stringWriter);
result.WriteXml(xmlTextwriter, XmlWriteMode.IgnoreSchema);
XmlNode xRoot = xReturn.CreateElement("root");
xReturn.AppendChild(xRoot);
xReturn.LoadXml(stringWriter.ToString());
return xReturn;
}
I put these functions into a class called HelperFunctions and added the class to an ASP.NET Web project.
To this, I added an ASP.NET Web Form (ASPX) called GetPriceHistory and edited the ASPX page to remove the HTML markup so that it looks like this:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="GetPriceHistory.aspx.cs"
Inherits="PriceHistoryService.GetPriceHistory" %>
The nice thing about this approach is that you can now write code that writes directly to the response buffer and set the response type so that you can write XML over HTTP.
Because the helper functions take strings for the ticker and for the start and end dates, you can use them as parameters to the ASPX.
You can then pass them to the helper functions to generate XML, which you then write out to the response buffer.
In addition, the MIME type needs to be set to "text/xml" so that any reader sees it as XML and not text.
Figure 3 shows the code to do that.
Remember that HelperFunctions is the name of a class containing the functions that build the Yahoo URI and that read it and convert the CSV data to XML.

Figure 3 Code for the Helper Functions
HelperFunctions hlp = new HelperFunctions();
protected void Page_Load(object sender, EventArgs e)
{
string strTicker, strStartDate, strEndDate;
if(Request.Params["ticker"]!=null)
strTicker = Request.Params["ticker"].ToString();
else
strTicker = "MSFT";
if(Request.Params["startdate"]!=null)
strStartDate = Request.Params["startdate"].ToString();
else
strStartDate = "1-1-2008";
if(Request.Params["enddate"]!=null)
strEndDate = Request.Params["enddate"].ToString();
else
strEndDate = "1-1-2009";
XmlDocument xReturn = hlp.getXML(strTicker, strStartDate, strEndDate);
Response.ContentType = "text/xml";
Response.Write(xReturn.OuterXml);
}
You now have a simple XML-over-HTTP service that returns time-series data.
Figure 4 shows an example of it in action.
Figure 4 A Simple XML-over-HTTP Service
Building a Data-Agnostic Service That Uses This Data
With server-generated visualization, a client renders an image, and all processing is done on the server.
Some very smart visualization engines provide code that can post back to the server to provide interactivity by using image maps in the image that is rendered back, but this is extremely complex to generate, and the functionality can be limited.
This approach is useful if you want to generate static charts that require no end-user runtime because the browser can render the common image formats.
Figure 5 shows a typical architecture for this approach.
Figure 5 Typical Server-Rendered Visualization Architecture
When you build this architecture, you usually write server code that understands the data.
In the previous case, for example, if you're writing a time-series chart that is plotting the Close value, you would write code that reads in the XML and takes the Close data and loads it into a series on the chart so that it can be plotted.
If you are using the Microsoft ASP.NET charting engine (which is freely downloadable; see the link later in this article), you'd typically define a chart like this:
<asp:Chart ID="Chart1" runat="server">
<Series>
<asp:Series Name="Series1">
</asp:Series>
</Series>
<ChartAreas>
<asp:ChartArea Name="ChartArea1">
</asp:ChartArea>
</ChartAreas>
</asp:Chart>
This approach, however, usually limits you to charting rather than visualization because the ability to provide interactivity is limited.
The ability to generate related metadata is also limited in this scenario because all requests require a post-back to the server to generate a new chart and would be limited to the functionality that is provided on the server.
The ability to overlay related metadata is also limited for the same reasons.
However, the important capabilities of data agnosticism can be enabled by this scenario.
It's relatively easy for you to configure metadata about your data source and where in the data source you can find your data series and data categories.
An engine can process this metadata and turn it into the series and categories that the server can render, making it easy to add new visualizations without a lot of extra programming.
Building a Data-Agnostic Visualization Server
There are a number of server-side charting technologies available, and the programming APIs change across them, but the principles that I discuss here are similar across all of them.
In this section, I'll look at the free ASP.NET charting engine from Microsoft.
You also need the Visual Studio add-ins for the Charting server.
Let's look at what it takes to build a pie chart with this charting engine.
The code is very simple.
First, add an instance of the chart control to an ASPX Web form.
You'll see something like this in the code view:
<asp:Chart ID="Chart1" runat="server">
<Series>
<asp:Series Name="Series1">
</asp:Series>
</Series>
<ChartAreas>
<asp:ChartArea Name="ChartArea1">
</asp:ChartArea>
</ChartAreas>
</asp:Chart>
Then write code like the following to render some data in the chart control:
double[] yValues = { 20, 10, 24, 23 };
string[] xValues = { "England", "Scotland", "Ireland", "Wales" };
Series mySeries = Chart1.Series[0];
mySeries.Points.DataBindXY(xValues, yValues);
mySeries.ChartType = SeriesChartType.Pie;
In this case, I've hard-coded the values, but you would usually read them from a database or from a service and then load them into the arrays before using them to generate the chart.
Of course, the reuse of this code becomes difficult, and any changes in the data source can break it, so let's take a look at writing something that doesn't need to be bound to the data type.
The nice thing about representing the data in XML is that I can use the XPath language to define where in the XML document the data I want to plot will come from.
For the data shown in Figure 1, the XPath statement that defines the location of the Close prices looks like this:
/NewDataSet/TimeSeries/Close
Now, if you think about it, instead of writing code that contains the definitions for your chart, you can externalize it as a configuration.
Imagine a configuration file like the one shown in Figure 6.

Figure 6 A Configuration File That Defines a Chart
<root>
<Chart Name="PriceHistory1">
<Uri>
<Path>http://localhost/PriceHistoryService/GetPriceHistory.aspx</Path>
<Param Name="ticker">MSFT</Param>
<Param Name="startdate">1-1-2008</Param>
<Param name="enddate">1-1-2009</Param>
</Uri>
<Data>
<SeriesDefinitions>
<Series id="ClosePrice">
<Data>/NewDataSet/TimeSeries/Close</Data>
<Type>Line</Type>
</Series>
</SeriesDefinitions>
</Data>
</Chart>
</root>
You're now defining a chart called PriceHistory1 that takes its data from the given URL, appending parameters with the given names and given values.
The values are hardcoded in this case, but there's nothing to stop you from writing code that uses parameters generated by an end user.
Additionally, the Series Definitions section defines a number of series with an XPath statement indicating where the data comes from and how to draw it.
Right now it uses a simple definition of a chart type, but you could include extra parameters here for color or other elements or for defining multiple series (it's XML after all, so it's easy to add extra nodes) as well as categories, labels, or other such metadata.
For this example I've kept it simple.
Now your charting-engine code will look vastly different.
Instead of writing code that reads the data, parses the data, and loads it directly into the chart, you can write code that reads the configuration, builds the service call URI from the configuration data, calls the service, gets the returned XML, and uses the XPath variables in the configuration to get the data series you want.
Under these conditions, your architecture can be much more robust.
Consider, for example, if the data source value changed its XML tag from Close to Closing Price.
You wouldn't have to edit or recompile your code; you'd simply edit the XPath variable in the chart definition.
It's not much of a stretch to think about how you would edit this to connect to different types of data sources, such as database connections or Web services.
Figure 7 shows the code that plots the time-series data on an ASP.NET chart.

Figure 7 Plotting the DTime-Series Data on an ASP.NET Chart
protected void Button1_Click(object sender, EventArgs e)
{
// Variable declarations
StringBuilder dataURI = new StringBuilder();
WebClient webClient = new WebClient();
XmlDocument xmlChartConfig = new XmlDocument();
XmlDocument xmlData = new XmlDocument();
// Get the chart config
Uri uri = new Uri(Server.MapPath("ChartConfig.xml"),
UriKind.RelativeOrAbsolute);
Stream configData = webClient.OpenRead(uri);
XmlTextReader xmlText = new XmlTextReader(configData);
xmlChartConfig.Load(xmlText);
// I'm hard coding to read in the chart called 'Price History 1'. In a
// 'real' environment my config would contain multiple charts, and I'd
// pass the desired chart (along with any parameters) in the request
// string. But for simplicity I've kept this hard coded.
XmlNodeList lst =
xmlChartConfig.SelectNodes("/root/Chart[@Name='PriceHistory1']/Uri/*");
// The first child contains the root URI
dataURI.Append(lst.Item(0).InnerText.ToString());
// The rest of the children of this node contain the parameters
// the first parameter is prefixed with ?, the rest with &
// i.e. http://url?firstparam=firstval&secondparam=secondval etc
for (int lp = 1; lp < lst.Count; lp++)
{
if (lp == 1)
dataURI.Append("?");
else
dataURI.Append("&");
// In this case the desired parameters are hard coded into the XML.
// in a 'real' server you'd likely accept them as params to this page
dataURI.Append(lst.Item(lp).Attributes.Item(0).Value.ToString());
dataURI.Append("=");
dataURI.Append(lst.Item(lp).InnerText);
}
// Now that we have the URI, we can call it and get the XML
uri = new Uri(dataURI.ToString());
Stream phData = webClient.OpenRead(uri);
xmlText = new XmlTextReader(phData);
xmlData.Load(xmlText);
// This simple example is hard coded for a particular chart
// ('PriceHistory1') and assumes only 1 series
lst = xmlChartConfig.SelectNodes(
"/root/Chart[@Name='PriceHistory1']/Data/SeriesDefinitions/Series/Data");
// I'm taking the first series, because I only have 1
// A 'real' server would iterate through all the matching nodes on the
// XPath
string xPath = lst.Item(0).InnerText;
// I've read the XPath that determines the data location, so I can
// create a nodelist from that
XmlNodeList data = xmlData.SelectNodes(xPath);
Series series = new Series();
// I'm hard coding for 'Line' here -- the 'real' server should
// read the chart type from the config
series.ChartType = SeriesChartType.Line;
double nCurrent = 0.0;
// I can now iterate through all the values of the node list, and
foreach (XmlNode nd in data)
{
// .. create a DataPoint from them, which is added to the Series
DataPoint d = new DataPoint(nCurrent, Convert.ToDouble(nd.
InnerText));
series.Points.Add(d);
nCurrent++;
}
// Finally I add the series to my chart
Chart1.Series.Add(series);
}
The results are shown in Figure 8.
No configuration has been done on the chart, and it's using the default configuration values, but the data is being read and being plotted.
Figure 8 The Results Generated by the Time-Series Data
A small tweak to the configuration file to give me volume and a different set of dates (1-1-1980 to 1-1-1990) provides the view in Figure 9—without changing a line of code in the charting service because it is data-agnostic.
Figure 9 New Results After Tweaking the Configuration File
Documenting how to build a data-agnostic server would take an entire book in its own right, and here I've just skimmed the surface.
The principles you've seen will apply to most APIs you work with, and the majority of the code you write should be for managing the external chart configuration to get the data, making what you've seen here very portable.
In this article, I looked at one of the main principles of building data visualizations—providing a way to render your data in a data-agnostic manner.
In a future article, I will explore using rich technologies on the client side to provide the ability to interact with your data and to smartly aggregate disparate data sources.
The power of the .NET platform is now available in the browser using Microsoft Silverlight, so we will use it to demonstrate these principles.
Laurence Moroney is a senior technology evangelist with Microsoft, specializing in Silverlight.
He is the author of many books on computing topics, including Silverlight, AJAX, interoperability, and security.
You can find Laurence's blog at blogs.msdn.com/webnext.
|
.NET Visualisierung
Visualisierung von Daten mit .NET
Laurence Moroney
In diesem Artikel wird Folgendes erläutert:
-
Datenvisualisierung
-
Gebäude Daten agnostischen Dienste
-
Erstellen einen Server Visualisierung
|
In diesem Artikel werden folgende Technologien verwendet:
C#, ASP.NET), XML
|

Inhalt
Informationen Visualisierung hat wurde um für eine lange Zeit, aber bitten unterschiedliche Personen Bedeutung, und erhalten Sie wahrscheinlich viele unterschiedliche Antworten – z. B. Diagramme, innovative animierte Grafiken oder rechenintensive Darstellungen komplexer Datenstrukturen.
Informationen Visualisierung kapselt alle diese Antworten, und eine Informationen Visualisierung Plattform ist, die jedes dieser Szenarien unterstützen kann.
Aus der Perspektive eines wissenschaftlichen ist Informationen Visualisierung in der Regel verwendet, um die Studie der visuellen Darstellung von umfangreiche Auflistungen von Informationen, die nicht unbedingt numerische Natur und die Verwendung der grafischen Darstellungen dieser Daten, damit die Daten analysiert und verstanden werden zu definieren.
Aus geschäftlicher Sicht geht Informationen Visualisierung Daten über die grafische Darstellung der die Daten mithilfe von Tools, mit denen End Benutzer interagieren mit den Daten um die Informationen finden, die Sie benötigen Wert ableiten.
Natürlich nicht nur die Möglichkeit, zeichnen Sie diese Bilder in der Regel müssen genug für eine gute Informationen Visualisierung Plattform;Es gibt auch andere Ebenen von Funktionen, die z. B. behoben werden müssen:
-
Interactivity kann Interaktivität von animiert die Bewegung der Segmente in der ein Kreisdiagramm zur Bereitstellung von Benutzern mit Tools für die Datenbearbeitung z. B. zum Vergrößern und verkleinern, der eine Time Series variieren.
-
Generieren Verwandte Metadaten haben viele Diagramme Wert über verwandte kontextbezogene Metadaten hinzugefügt.
Wenn Sie eine Time Series-Diagramm anzeigen, sollten Sie generieren einen gleitenden Durchschnitt und optimieren den Zeitraum für diese Gleitender Durchschnitt oder experimentieren Sie mit was-wenn-Szenarien.
Es ist nicht möglich, eine Datenquelle für all diese Datenansichten für Sie generieren erwarten.
Einige Form der Datenbearbeitung ist auf der Präsentationsebene erforderlich.
-
Überlagern von verwandten eine allgemeine Anforderung für Diagramme besteht darin, andere Stimuli betrachten, die möglicherweise Auswirkungen auf die Daten und die Visualisierung dies widerspiegeln.
Erwägen Sie eine Time Series, Lagerwert des Unternehmens und einen Feed von Newsbeiträgen über die bestimmten Aktie anzeigt.
Reale Wert kann auf das Diagramm durch anzeigen, wie der Wert, die News beeinflusst hinzugefügt werden. "
Guten"News möglicherweise machen, gehen "falsche" "News möglicherweise diese Verbund zu machen.
Möglichkeit, diese Daten dem Time Series-Diagramm hinzufügen wird es aus einem einfachen Diagramm Informationen Visualisierung.
Der Schlüssel zum Erstellen einer Visualisierung-Plattform, die alle diese aktivieren können ist Flexibilität, so dass Sie alle Daten in keiner Weise jederzeit rendern können.
Dies ist eine riesige und in der Regel spezielle Aufwand, jedoch eine Technik, mit denen Sie diese Bemühungen erleichtern können mit mit Daten Agnotisticism verwenden.
Agnosticism Daten entsteht, wenn Sie eine Architektur definieren für Visualisierung von Daten, die die Daten selbst abhängig ist.
Wenn Sie das Beispiel für eine Time Series-Diagramm in Betracht, die zugehörigen Metadaten bereitstellt ziehen, ist es z. B. recht einfach zu programmieren eine Anwendung der Time Series-Daten und die zugehörigen Metadaten (z. B. ein Newsfeed) lesen und Schreiben der Daten auf auf dem Bildschirm zum Erstellen von Diagrammen Datenbankmodul verwenden.
Nachdem Sie dies getan haben, ist der Aufwand jedoch gut für diese Darstellung und diese Darstellung allein.
Die Anwendung, die Sie geschrieben haben, ist eng an den Daten selbst gebunden.
Das Prinzip der Daten Agnosticism ermöglicht das Auswählen einer Datenquelle, definieren die gewünschten Daten und Teilen Sie die Visualisierung-Engine wechseln, und zeichnen Sie es jedoch soll es.
Wir betrachten eine zum Erstellen von einer einfachen Version dieses Modul in diesem Artikel.
Einführung
Wie bei allem, ist es ratsam, mit der Daten beginnen.
In diesem Abschnitt erhalten ich eine kurze Übersicht über einen einfachen XML-über-HTTP-Dienst, die bereitgestellten Dienste Yahoo Time Series-Daten bereitstellt.
Der Yahoo Time Series-Dienst gibt eine CSV-Datei mit grundlegende Time Series-Daten mit den folgenden Feldern: Datum, Preis, Closing Preis, hoch, Niedrig, Datenträger öffnen und schließen angepasst.
Die API aufrufen, es ist sehr einfach:
ichart.Finance.Yahoo.com/Table.CSV
Sie verwenden die folgenden Parameter:
|
Abbildung 1 Größe und Access Zeiten mit nicht lokalen Speicher
|
|
Parameter
|
Wert
|
|
s
|
Stock Ticker (z. B. MSFT)
|
|
ein
|
Starten Sie Monat (0-basiert;0 = Januar, 11 = Dezember)
|
|
b
|
Starten von Tag
|
|
c
|
Starten Sie Jahr
|
|
d
|
Ende Monat (0-basiert;0 = Januar, 11 = Dezember)
|
|
e
|
Ende-Tag
|
|
f
|
Ende Jahr
|
|
g
|
Verwenden Sie immer das Buchstaben d
|
|
ignorieren
|
Verwenden Sie immer den Wert ".csv"
|
Um die Time Series-Daten für Microsoft (MSFT) von January 1, 2008 zu 1 Januar 2009, gelangen verwenden Sie den folgenden URL:
Abbildung 1 zeigt einer C#-Funktion, nimmt Zeichenfolgenparameter für das Tickersymbol, Anfangstermin und End Datum, und dieser URI erstellt.

Abbildung 1 C#-Funktion, die einen URI zu Capture-Daten zu Animationen
public string BuildYahooURI(string strTicker,
string strStartDate, string strEndDate)
{
string strReturn = "";
DateTime dStart = Convert.ToDateTime(strStartDate);
DateTime dEnd = Convert.ToDateTime(strEndDate);
string sStartDay = dStart.Day.ToString();
string sStartMonth = (dStart.Month -1).ToString();
string sStartYear = dStart.Year.ToString();
string sEndDay = dEnd.Day.ToString();
string sEndMonth = (dEnd.Month - 1).ToString();
string sEndYear = dEnd.Year.ToString();
StringBuilder sYahooURI =
new StringBuilder("http://ichart.finance.yahoo.com/table.csv?s=");
sYahooURI.Append(strTicker);
sYahooURI.Append("&a=");
sYahooURI.Append(sStartMonth);
sYahooURI.Append("&b=");
sYahooURI.Append(sStartDay);
sYahooURI.Append("&c=");
sYahooURI.Append(sStartYear);
sYahooURI.Append("&d=");
sYahooURI.Append(sEndMonth);
sYahooURI.Append("&e=");
sYahooURI.Append(sEndDay);
sYahooURI.Append("&f=");
sYahooURI.Append(sEndYear);
sYahooURI.Append("&g=d");
sYahooURI.Append("&ignore=.csv");
strReturn = sYahooURI.ToString();
return strReturn;
}
Nun, den URI für die Daten haben, benötigen Sie zum Lesen und zu seiner Verwendung.
In diesem Fall werde ich die CSV-Daten in XML konvertieren.
Eine Funktion, die dies tun kann ist in Abbildung 2 dargestellt.

Abbildung 2 CSV-Daten in XML konvertieren
public XmlDocument getXML(string strTicker,
string strStartDate, string strEndDate)
{
XmlDocument xReturn = new XmlDocument();
DataSet result = new DataSet();
string sYahooURI =
BuildYahooURI(strTicker, strStartDate, strEndDate);
WebClient wc = new WebClient();
Stream yData = wc.OpenRead(sYahooURI);
result = GenerateDataSet(yData);
StringWriter stringWriter = new StringWriter();
XmlTextWriter xmlTextwriter = new XmlTextWriter(stringWriter);
result.WriteXml(xmlTextwriter, XmlWriteMode.IgnoreSchema);
XmlNode xRoot = xReturn.CreateElement("root");
xReturn.AppendChild(xRoot);
xReturn.LoadXml(stringWriter.ToString());
return xReturn;
}
Ich legen Sie diese Funktionen in eine Klasse namens HelperFunctions und einem ASP.NET-Webprojekt die Klasse hinzugefügt.
Dazu hinzugefügt ich ein ASP.NET Web Forms (ASPX) GetPriceHistory aufgerufen und bearbeitet die ASPX-Seite HTML-Markup entfernen, sodass er wie folgt aussieht:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="GetPriceHistory.aspx.cs"
Inherits="PriceHistoryService.GetPriceHistory" %>
Nettes Vorteil dieses Ansatzes befindet, können jetzt die schreiben Sie Code, der direkt in den Antwort-Puffer schreibt und den Antworttyp festlegen, sodass Sie XML über HTTP schreiben können.
Da die Hilfsfunktionen Zeichenfolgen für das Tickersymbol und Anfangs- und Endtermine nutzen, können Sie Sie als Parameter an die ASPX-verwenden.
Sie können dann diese an übergeben der Hilfsfunktionen zum Generieren von XML, die Sie dann in den Antwort-Puffer schreiben.
Darüber hinaus muss der MIME-Typ "Text/xml" festgelegt werdenDamit alle Leser es als XML und nicht Text erkennt.
Abbildung 3 zeigt den Code zu diesem Zweck.
Beachten Sie, dass HelperFunctions den Namen einer Klasse mit die Funktionen, Yahoo-URI erstellen und lesen und konvertieren Sie die CSV-Daten in XML.

Abbildung 3-Code für die Hilfsfunktionen
HelperFunctions hlp = new HelperFunctions();
protected void Page_Load(object sender, EventArgs e)
{
string strTicker, strStartDate, strEndDate;
if(Request.Params["ticker"]!=null)
strTicker = Request.Params["ticker"].ToString();
else
strTicker = "MSFT";
if(Request.Params["startdate"]!=null)
strStartDate = Request.Params["startdate"].ToString();
else
strStartDate = "1-1-2008";
if(Request.Params["enddate"]!=null)
strEndDate = Request.Params["enddate"].ToString();
else
strEndDate = "1-1-2009";
XmlDocument xReturn = hlp.getXML(strTicker, strStartDate, strEndDate);
Response.ContentType = "text/xml";
Response.Write(xReturn.OuterXml);
}
Sie haben nun einen einfachen XML-über-HTTP-Dienst, der Time Series-Daten zurückgibt.
Abbildung 4 zeigt ein Beispiel der in Aktion.
Abbildung 4 eine einfache XML-über-HTTP- Dienst
Erstellen eines Dienstes Daten agnostischen, diese Daten verwendet
Serverseitig generierte Visualisierung ein Client rendert ein Bild und alle Verarbeitung erfolgt auf dem Server.
Einige sehr intelligente Visualisierung Module bieten Code, der an den Server über Imagemaps in dem Bild, das wieder wiedergegeben wird bieten Interaktivität buchen kann, aber dies ist äußerst komplex zum Generieren, und die Funktionalität kann begrenzt werden.
Dieser Ansatz ist hilfreich, wenn Sie statische Diagramme generieren, die keine Endbenutzer Laufzeit erfordern, da der Browser die allgemeinen Bildformate rendern kann.
Abbildung 5 zeigt eine typische Architektur für diesen Ansatz.
Abbildung 5 Typical Server-Rendered Visualisierung Architektur
Wenn Sie diese Architektur erstellen, Schreiben Sie in der Regel Servercode, der die Daten zu verstehen.
Im vorherigen Fall z. B. würde Wenn Sie ein Diagramm Time Series schreiben, das Zeichnen von den schließen-Wert, Sie Code schreiben, die in der XML-Datei liest und übernimmt die schließen Daten in einer Datenreihe im Diagramm lädt, sodass es gezeichnet werden kann.
Wenn Sie den Diagramm-Modul (der kostenlos herunterladbares; ist Microsoft ASP.NET verwendenSiehe der Link weiter unten in diesem Artikel), Sie in der Regel ein Diagramm wie folgt definieren möchten:
<asp:Chart ID="Chart1" runat="server">
<Series>
<asp:Series Name="Series1">
</asp:Series>
</Series>
<ChartAreas>
<asp:ChartArea Name="ChartArea1">
</asp:ChartArea>
</ChartAreas>
</asp:Chart>
Dieser Ansatz begrenzt jedoch normalerweise Sie auf Diagramme statt Visualisierung, da die Möglichkeit, Interaktivität bereitzustellen beschränkt ist.
Die Möglichkeit, verwandte Metadaten generieren ist in diesem Szenario auch begrenzt, da alle Anforderungen ein Sendevorgangs an den Server ein neues Diagramm zu generieren und wäre beschränkt auf die Funktionalität, die auf dem Server bereitgestellt wird.
Die Möglichkeit, verwandte Metadaten überlagern ist auch für den gleichen Gründen beschränkt.
Wichtigen Funktionen von Agnosticism Daten können jedoch durch dieses Szenario aktiviert werden.
Es ist relativ einfach, konfigurieren Metadaten zu Ihrer Datenquelle und dem in der Datenquelle Sie Ihre Datenreihen und Datenkategorien finden können.
Ein Modul verarbeiten Sie diese Metadaten und schalten Sie ihn in den Reihen und Kategorien, die der Server wiedergeben kann, erleichtert das Hinzufügen von neuer Visualisierungen ohne großen kann zusätzliche Programmierung.
Erstellen einen Data-agnostischen Visualisierung Server
Stehen eine Reihe von serverseitigen Diagrammerstellung Technologien zur Verfügung, und die Programmierung APIs über diese ändern, aber die Prinzipien, die ich hier besprechen ähneln aller von Ihnen.
In diesem Abschnitt werde ich an die kostenlosen Diagrammerstellung ASP.NET-Modul aus Microsoft.
Müssen Sie auch die Add-Ins von Visual Studio für die Diagrammdarstellung Server.
Untersuchen wir, was es dauert, um ein Kreisdiagramm mit diesem Modul zum Erstellen von Diagrammen zu erstellen.
Der Code ist sehr einfach.
Fügen Sie zunächst eine Instanz des Chart-Steuerelement zu einer ASPX-Webformular.
Etwas wird in der Codeansicht angezeigt werden:
<asp:Chart ID="Chart1" runat="server">
<Series>
<asp:Series Name="Series1">
</asp:Series>
</Series>
<ChartAreas>
<asp:ChartArea Name="ChartArea1">
</asp:ChartArea>
</ChartAreas>
</asp:Chart>
Dann schreiben Sie Code wie den folgenden um einige Daten im Diagramm-Steuerelement rendern:
double[] yValues = { 20, 10, 24, 23 };
string[] xValues = { "England", "Scotland", "Ireland", "Wales" };
Series mySeries = Chart1.Series[0];
mySeries.Points.DataBindXY(xValues, yValues);
mySeries.ChartType = SeriesChartType.Pie;
In diesem Fall ich habe hart codiert die Werte, aber Sie würden normalerweise aus einer Datenbank oder von einem Dienst gelesen und anschließend in den Arrays laden, bevor Sie das Diagramm zu generieren.
Natürlich die Wiederverwendung dieses Codes wird schwierig, und alle Änderungen in der Datenquelle heben, wir etwas schreiben betrachten, die nicht den Datentyp gebunden werden müssen.
Die gute Darstellung der Daten in XML ist, dass ich zum Definieren von im XML-Dokument, in denen die Daten, die gezeichnet werden soll aus stammen werden die XPath-Sprache verwenden können.
Für die Daten in Abbildung 1 angezeigt wird sieht die XPath-Anweisung, die den Speicherort der schließen Preise definiert:
/ NewDataSet/TimeSeries/schließen
Nun, wenn Sie Informationen darüber, anstatt schreiben Code, die Definitionen für Ihr Diagramm enthält, können Sie es als Konfiguration auf externalize.
Genommen Sie an, eine Konfigurationsdatei wie dargestellt in Abbildung 6.

Abbildung 6 A-Konfigurationsdatei, die einem Diagramm definiert
<root>
<Chart Name="PriceHistory1">
<Uri>
<Path>http://localhost/PriceHistoryService/GetPriceHistory.aspx</Path>
<Param Name="ticker">MSFT</Param>
<Param Name="startdate">1-1-2008</Param>
<Param name="enddate">1-1-2009</Param>
</Uri>
<Data>
<SeriesDefinitions>
<Series id="ClosePrice">
<Data>/NewDataSet/TimeSeries/Close</Data>
<Type>Line</Type>
</Series>
</SeriesDefinitions>
</Data>
</Chart>
</root>
Sie können jetzt definieren ein Diagramm PriceHistory1 aufgerufen, die die Daten aus dem angegebenen URL enthält Anfügen von Parametern mit den angegebenen Namen und angegebenen Werten.
Die Werte sind in diesem Fall hartcodierte, aber es gibt nichts zu verhindern, dass Sie Code, die von einem Endbenutzer generierten Parameter verwendet.
Darüber hinaus definiert Abschnitt Reihe Definitionen eine Anzahl von Reihen mit einer XPath-Anweisung, wo die Daten stammen und wie es gezeichnet angibt.
Rechts jetzt eine einfache Definition einen Diagrammtyp verwendet, Sie konnte jedoch zusätzliche-Parameter hier für Farbe oder anderen Elementen oder für mehrere Datenreihen (es ist XML, so dass Sie auf einfache Weise zusätzliche Knoten hinzufügen) ebenso wie Kategorien, Etiketten oder andere solche Metadaten definieren.
Für dieses Beispiel habe ich es einfache gehalten.
Jetzt wird der Code Diagrammerstellung Modul enorm verschiedene aussehen.
Anstatt Code, der die Daten liest, analysiert die Daten und lädt es direkt in das Diagramm zu schreiben, können Sie Code schreiben, die liest der Konfiguration, den Service-Aufruf URI aus der Konfigurationsdaten erstellt, ruft der Dienst, ruft die zurückgegebene XML und verwendet die XPath-Variablen in der Konfiguration um die Datenreihe abzurufen soll.
Unter diesen Bedingungen kann Ihre Architektur viel robuster.
Betrachten Sie z. B., wenn der Quellwert Daten das XML--Tag schließen, um Closing Preis geändert.
Würde nicht müssen Sie bearbeiten oder Kompilieren des Codes;Sie würden die XPath-Variable in der Diagramm-Definition einfach bearbeiten.
Es ist nicht viel von einer Strecken kümmern, wie Sie hier, um verschiedene Arten von Datenquellen wie z. B. Datenbankverbindungen oder Webdienste Verbindung bearbeiten würden.
Abbildung 7 zeigt den Code, der Time Series-Daten auf ein Diagramm ASP.NET zeichnet.

Abbildung 7 Zeichnung der DTime-Serie-Daten auf ein ASP.NET ein
protected void Button1_Click(object sender, EventArgs e)
{
// Variable declarations
StringBuilder dataURI = new StringBuilder();
WebClient webClient = new WebClient();
XmlDocument xmlChartConfig = new XmlDocument();
XmlDocument xmlData = new XmlDocument();
// Get the chart config
Uri uri = new Uri(Server.MapPath("ChartConfig.xml"),
UriKind.RelativeOrAbsolute);
Stream configData = webClient.OpenRead(uri);
XmlTextReader xmlText = new XmlTextReader(configData);
xmlChartConfig.Load(xmlText);
// I'm hard coding to read in the chart called 'Price History 1'. In a
// 'real' environment my config would contain multiple charts, and I'd
// pass the desired chart (along with any parameters) in the request
// string. But for simplicity I've kept this hard coded.
XmlNodeList lst =
xmlChartConfig.SelectNodes("/root/Chart[@Name='PriceHistory1']/Uri/*");
// The first child contains the root URI
dataURI.Append(lst.Item(0).InnerText.ToString());
// The rest of the children of this node contain the parameters
// the first parameter is prefixed with ?, the rest with &
// i.e. http://url?firstparam=firstval&secondparam=secondval etc
for (int lp = 1; lp < lst.Count; lp++)
{
if (lp == 1)
dataURI.Append("?");
else
dataURI.Append("&");
// In this case the desired parameters are hard coded into the XML.
// in a 'real' server you'd likely accept them as params to this page
dataURI.Append(lst.Item(lp).Attributes.Item(0).Value.ToString());
dataURI.Append("=");
dataURI.Append(lst.Item(lp).InnerText);
}
// Now that we have the URI, we can call it and get the XML
uri = new Uri(dataURI.ToString());
Stream phData = webClient.OpenRead(uri);
xmlText = new XmlTextReader(phData);
xmlData.Load(xmlText);
// This simple example is hard coded for a particular chart
// ('PriceHistory1') and assumes only 1 series
lst = xmlChartConfig.SelectNodes(
"/root/Chart[@Name='PriceHistory1']/Data/SeriesDefinitions/Series/Data");
// I'm taking the first series, because I only have 1
// A 'real' server would iterate through all the matching nodes on the
// XPath
string xPath = lst.Item(0).InnerText;
// I've read the XPath that determines the data location, so I can
// create a nodelist from that
XmlNodeList data = xmlData.SelectNodes(xPath);
Series series = new Series();
// I'm hard coding for 'Line' here -- the 'real' server should
// read the chart type from the config
series.ChartType = SeriesChartType.Line;
double nCurrent = 0.0;
// I can now iterate through all the values of the node list, and
foreach (XmlNode nd in data)
{
// .. create a DataPoint from them, which is added to the Series
DataPoint d = new DataPoint(nCurrent, Convert.ToDouble(nd.
InnerText));
series.Points.Add(d);
nCurrent++;
}
// Finally I add the series to my chart
Chart1.Series.Add(series);
}
Die Ergebnisse werden in Abbildung acht angezeigt.
Im Diagramm wurde keine Konfiguration durchgeführt wurde und es ist die Standard-Konfigurationswerte verwenden, aber die Daten wird gelesen und dargestellt wird.
Abbildung 8 der Ergebnisse generiert durch Zeitreihen Daten
Eine kleine Tweak der Konfigurationsdatei, damit ich Datenträger und einen anderen Satz von Daten (1-1-1980, 1-1-1990) stellt die Ansicht in Abbildung 9 – ohne eine Codezeile in der Diagramm-Dienst ändern, da er Daten agnostischen ist.
Abbildung 9 neue Ergebnisse nach optimiert, die Konfigurationsdatei
Dokumentieren zum Erstellen von eines Daten-agnostischen Servers würde ein ganzes Buch in seinen eigenen rechts; ich habe hier nur die Oberfläche des skimmed.
Die Prinzipien, die Sie gesehen haben gelten für die meisten APIs, die Sie arbeiten und den Großteil der von Ihnen sein sollte geschriebenen, für die Verwaltung der Konfiguration externe Diagramm zu die Daten vornehmen, was Sie hier gesehen haben sehr tragbaren Code.
In diesem Artikel ich haben eine der wichtigsten Prinzipien Daten Visualisierungen erstellen – eine Möglichkeit, Ihre Daten eine Daten-agnostischen Weise zu rendern.
In einem zukünftigen Artikel wird ich untersuchen, über eine umfangreiche Technologien auf dem Client die Möglichkeit, um mit Ihren Daten zu interagieren und smartly verschiedenartigen Datenquellen zu aggregieren.
Die Leistungsfähigkeit von .NET Plattform ist jetzt verfügbar in den Browser mit Microsoft Silverlight, so dass wir es verwendet, um diese Prinzipien zu veranschaulichen.
Laurence Moroney ist ein leitender Technologie Evangelist mit Microsoft Silverlight spezialisiert.
Er ist Autor zahlreicher Bücher über Themen, einschließlich Silverlight, AJAX, Interoperabilität und Sicherheit der Datenverarbeitung.
Sie finden die Laurence's Blog unter blogs.msdn.com/webnext.
|
|
| Tip: Click the printer button in your browser toolbar to get the printer friendly version of this article. |
|