Solved

read values into array

Posted on 2004-08-22
9
342 Views
Last Modified: 2008-03-10
HI,
I have the following code which draws a chart to the screen and plots co-ordinates onto it. (finally spat out as a jpg to the browser).
At the moment for dev/testing purposes I am hard coding the x,y values but I need to be able to read them from an external datasource... be it a DB or xml or text file.

(code snippet)
void Page_Load(Object sender, EventArgs e) {
LineChart c = new LineChart(840, 580, Page);
c.Title="";
c.OpenFooter = "Opens";
c.CloseFooter = "Closes";
c.MidFooter = " <-------- voting days --------> ";
c.Xorigin=0; c.ScaleX=21; c.Xdivs=21;
c.Yorigin=0; c.ScaleY=25000; c.Ydivs=10;
c.AddValue(0,0);
c.AddValue(1,800);
c.AddValue(2,1100);
c.AddValue(3,2200);
c.AddValue(4,3600);
c.AddValue(5,4000);
c.AddValue(6,4105);
c.AddValue(7,5251);
c.AddValue(8,5299);
c.AddValue(9,6099);
c.AddValue(10,9090);
c.AddValue(11,12071);
c.AddValue(12,14500);
c.AddValue(13,16559);
c.AddValue(14,18222);
c.AddValue(15,18755);
c.AddValue(16,19444);
c.AddValue(17,20051);
c.AddValue(18,21222);
c.AddValue(19,21259);
c.AddValue(20,23451);
c.AddValue(21,23499);
c.Draw();
}
(/snippet)


Any ideas? I fairly new to C# so go easy on me please  :)
Cheers
0
Comment
Question by:QPR
  • 4
  • 3
  • 2
9 Comments
 
LVL 3

Accepted Solution

by:
ruff_ryder earned 250 total points
ID: 11865871
Assuming you have your points in a nXML file with the following structure:

<LinePoints>
     <point x="1" y="2" />
     <point x="3" y="4" />
     <point x="5" y="6" />
</LinePoints>

then you could read them back as follows in C#:

XmlDocument configXml = new XmlDocument();
configXml.Load("myxmlfile.xml");
                  
XmlNodeList topLevelSections = configXml.GetElementsByTagName("LinePoints");
if( topLevelSections.Count <= 0 )
      return;

foreach(XmlNode child in topLevelSections[0].ChildNodes)
{
      if( child.Name != "point" )
            continue;

      c.AddValue( Convert.ToInt32(((XmlAttribute)child.Attributes.GetNamedItem("x")).Value),
                          Convert.ToInt32(((XmlAttribute)child.Attributes.GetNamedItem("y")).Value) );
}


Ofcourse you would put all that code in a try-catch block
0
 
LVL 4

Expert Comment

by:ErikPhilips
ID: 11865896
(MS Access DB access via OleDB)

using System.Data.OleDb;

System.Data.OleDb.OleDbConnection DBconnection;  //connection to database
System.Data.OleDb.OleDbCommand    DbSelect;      // command to send to DB

DBconnection = new OleDbConnection();
DBconnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Password=\"\";User ID=Admin;Data Source=C:\\Database.mdb;Mode=Share Deny None;Extended Properties=\"\";Jet OLEDB:System database=\"\";Jet OLEDB:Registry Path=\"\";Jet OLEDB:Database Password=\"\";Jet OLEDB:Engine Type=5;Jet OLEDB:Database Locking Mode=1;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password=\"\";Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False";
try                              
{
      DBconnection.Open();
}
catch (Exception ex)
{
      Console.WriteLine(ex.Message);
}

listBox1.Items.Clear();
string Sql = "SELECT field1 FROM table1";    //SQL select statement
DbSelect = new OleDbCommand(Sql, DBconnection);  //create my command using the sql string connection using the db connection
DbSelect.Prepare();   // tell the sql server to prepare the statement
OleDbDataReader myReader = DbSelect.ExecuteReader();  // create a "datareader" which will read rows from the results
try
{
      while (myReader.Read())   // while there is data in the returned rows
      {
            listBox1.Items.Add(myReader.GetString(0));  // reader get column 0 as a string, add it to the listbox
      }
}
finally
{
      myReader.Close();
}

0
 
LVL 4

Expert Comment

by:ErikPhilips
ID: 11865905
(note i created my connection string by dropping a OleDbConnection onto the form, created the connectionString using the IDE, copied the string to memory and deleted the non-visual component.  You could do the same by droping components onto your application)
0
Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 29

Author Comment

by:QPR
ID: 11865996
Hi Ruff Rider.
This looks to be along the lines of what I need.
The X,Y values will be added on a daily basis... is basically a voting thing.
Each day a (non-web/tech) person will add a number via an admin page which will then cause the xml file to be opened and a new <point x=, y= /> tag to be added.... (no idea how to achieve this step but I guess that's a new question for another group!  :o) where X = day numberX and Y being the number of voting papers returned as at that date (X)

Would you recommend having the required number of tags (21) with the future days being blank
Example:
<LinePoints>
     <point x="1" y="100" />
     <point x="2" y="450" />
     <point x="3" y="612" />
     <point x= y= />
     <point x= y= />
   ...etc
</LinePoints>

or add a new line <point x= y= /> each time/day the user uses the admin page?
I see problems converting null to int32 but then I also see problems having less tags than the specified chart set-up. This probably makes little sense without seeing the code in it's entirity so I'll paste it all here in case it helps.
Continued thanks!


<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Drawing.Drawing2D" %>
<%@ Import Namespace="System.Drawing.Imaging" %>


<script language="C#" runat="server">

class LineChart
{
public Bitmap b;
public string Title="Default Title";
public string OpenFooter = "Default Footer";
public string CloseFooter="Default Footer";
public string MidFooter="Default Footer";
public ArrayList chartValues = new ArrayList();
public float Xorigin=0, Yorigin=0;
public float ScaleX, ScaleY;
public float Xdivs=2, Ydivs=2;

private int Width, Height;
private Graphics g;
private Page p;

struct datapoint {
public float x;
public float y;
public bool valid;
}

//initialize
public LineChart(int myWidth, int myHeight, Page myPage) {
Width = myWidth; Height = myHeight;
ScaleX = myWidth; ScaleY = myHeight;
b = new Bitmap(myWidth, myHeight);
g = Graphics.FromImage(b);
p = myPage;
}

public void AddValue(int x, int y) {
datapoint myPoint;
myPoint.x=x;
myPoint.y=y;
myPoint.valid=true;
chartValues.Add(myPoint);
}

public void Draw() {
int i;
float x, y, x0, y0;
string myLabel;
Pen blackPen = new Pen(Color.Blue,1);
Brush blackBrush = new SolidBrush(Color.Black);
Font axesFont = new Font("arial",10);

//first establish working area
p.Response.ContentType="image/Gif";
g.FillRectangle(new
SolidBrush(Color.LightYellow),0,0,Width,Height);
int ChartInset = 50;
int ChartWidth = Width-(2*ChartInset);
int ChartHeight = Height-(2*ChartInset);
g.DrawRectangle(new
Pen(Color.Black,2),ChartInset,ChartInset,ChartWidth,ChartHeight);

//must draw all text items before doing the rotate below
g.DrawString(Title, new Font("verdana",16), blackBrush, Width/2 - 290, 10);
g.DrawString(OpenFooter, new Font("Arial",8), blackBrush,Width/Width + 30, Height - 20);
g.DrawString(MidFooter,new Font("Arial",10), blackBrush,Width/2 - 50, Height - 25);
g.DrawString(CloseFooter,new Font("Arial",8), blackBrush,Width-65, Height - 20);

//draw X axis labels
for(i=0; i<=Xdivs; i++) {
      x=ChartInset+(i*ChartWidth)/Xdivs;
      y=ChartHeight+ChartInset;
      myLabel = (Xorigin + (ScaleX*i/Xdivs)).ToString();
      g.DrawString(myLabel, axesFont, blackBrush, x-4, y+10);
      g.DrawLine(blackPen, x, y+2, x, y-2);
}
//draw Y axis labels
for(i=0; i<=Ydivs; i++) {
      x=ChartInset;
      y=ChartHeight+ChartInset-(i*ChartHeight/Ydivs);
      myLabel = (Yorigin + (ScaleY*i/Ydivs)).ToString();
      g.DrawString(myLabel, axesFont, blackBrush, 5, y-6);
      g.DrawLine(blackPen, x+2, y, x-2, y);
}

//transform drawing coords to lower-left (0,0)
g.RotateTransform(180);
g.TranslateTransform(0,-Height);
g.TranslateTransform(-ChartInset,ChartInset);
g.ScaleTransform(-1, 1);

//draw chart data
datapoint prevPoint = new datapoint();
prevPoint.valid=false;
foreach(datapoint myPoint in chartValues) {
if(prevPoint.valid==true) {
      x0=ChartWidth*(prevPoint.x-Xorigin)/ScaleX;
      y0=ChartHeight*(prevPoint.y-Yorigin)/ScaleY;
      x=ChartWidth*(myPoint.x-Xorigin)/ScaleX;
      y=ChartHeight*(myPoint.y-Yorigin)/ScaleY;
      g.DrawLine(blackPen,x0,y0,x,y);
      g.FillEllipse(blackBrush,x0-2,y0-2,4,4);
      g.FillEllipse(blackBrush,x-2,y-2,4,4);
}
prevPoint = myPoint;
}

//finally send graphics to browser
b.Save(p.Response.OutputStream, ImageFormat.Gif);
}

~LineChart() {
g.Dispose();
b.Dispose();
}
}


void Page_Load(Object sender, EventArgs e) {
LineChart c = new LineChart(840, 580, Page);
c.Title="Number of returned voting papers as at " + System.DateTime.Today.ToString("dd/MM/yyyy");
c.OpenFooter = "Opens";
c.CloseFooter = "Closes";
c.MidFooter = " <-------- voting days --------> ";
c.Xorigin=0; c.ScaleX=21; c.Xdivs=21;
c.Yorigin=0; c.ScaleY=25000; c.Ydivs=10;
c.AddValue(0,0);
c.AddValue(1,800);
c.AddValue(2,1100);
c.AddValue(3,2200);
c.AddValue(4,3600);
c.AddValue(5,4000);
c.AddValue(6,4105);
c.AddValue(7,5251);
c.AddValue(8,5299);
c.AddValue(9,6099);
c.AddValue(10,9090);
c.AddValue(11,12071);
c.AddValue(12,14500);
c.AddValue(13,16559);
c.AddValue(14,18222);
c.AddValue(15,18755);
c.AddValue(16,19444);
c.AddValue(17,20051);
c.AddValue(18,21222);
c.AddValue(19,21259);
c.AddValue(20,23451);
c.AddValue(21,23499);
c.Draw();
}

</script>

0
 
LVL 3

Expert Comment

by:ruff_ryder
ID: 11866116
Hey,

Either way will work actually. Generating new nodes for the XML is pretty simple in .NET. However, since you say that the chart cannot deal with less than 21 days then it is better to code to suit the chart behaviour. It will mean less ahssles for you in functionality. There are a few approaches you could take:

1) Add points as they are entered.

In this case, the only points that would exist in your XML file are actual points input to the system. This would continue to work as you have it.

2) Pre-Allocate the 21 points and default their values

This approach accomodates the chart's operations. In this case, though, when adding a new entry you would have to index into the points and set teh corresponding data values.

Either way can work. Personally I would take approach one. I don't like having unused data in my system for perofrmance and resource issues. I don't know how this affects your chart though so the call is really yours :)

To help you out, have a look at the System.Xml namespace in the .NET documentation. You will find all classes you need to manipulate your xml file at runtime.
0
 
LVL 29

Author Comment

by:QPR
ID: 11866397
Getting there!
Man C# is picky when you come from a VB background (not a bad thing tho) XML != Xml

ok "Could not find file "C:\WINNT\system32\GraphData.xml""
The xml file is in the same folder as the aspx
In ASP classic (VBScript) I would use server.mapPath. How can I achieve this in C#.
Hopefully, after 2 forgotten ; and 10 upper/lower case errors :)

Also.... how can I paste text as plain text into VS.Net? When I paste from here I get font declarations etc... I see no paste special on the menu.
And.... Why is there no Intellisense? Is this because I am doing aspx as opposed to a vb.net file?
0
 
LVL 29

Author Comment

by:QPR
ID: 11866442
works like a charm and I learnt stuff into the bargain (always a bonus!)
I've used the absolute file path to the xml file and doubled up on the backslashes but would still like a relative path to it if possible?

Now to learn how to open/append the xml file/child tags

Many thanks
Jay
0
 
LVL 3

Expert Comment

by:ruff_ryder
ID: 11866468
Hey QPR,

For the MapPath, have a look at the System.Web.UI.Page object. It has a method called MapPath() that may be what you are looking for.

As for the text pasting, I'm not sure why that happens. Try pasting in notepad text file then paste from there. You should have intellisense when you are editing code. I don't think IntelliSense operates on the actual aspx page editor. You should have it when editing the code behind the aspx page though.
0
 
LVL 29

Author Comment

by:QPR
ID: 11866547
Thanks I'll have a look at MapPath() thanks.
Yep I'll revert to that, starnge that the IDE doesn't offer paste options though.

From memory this page/code was originally an aspx example I d/l as a zip file which I then just opened in VS.NET... as a result I can't find any code behind etc.
Only ever opened as a single file as opposed to a project/solution. Maybe that explains the lack of intellisense.

Many thanks for all the help RR.
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Cant save 3D 4 23
Get distinct values from excel or comm seperated file 4 30
Change to file doesn't show up 16 51
Why use this lambda? 12 33
Introduction This article series is supposed to shed some light on the use of IDisposable and objects that inherit from it. In essence, a more apt title for this article would be: using (IDisposable) {}. I’m just not sure how many people would ge…
This article describes a simple method to resize a control at runtime.  It includes ready-to-use source code and a complete sample demonstration application.  We'll also talk about C# Extension Methods. Introduction In one of my applications…
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question