Another C# help question

Associate
Joined
26 Apr 2009
Posts
204
I keep trying to approach this from various points of view, but I just keep getting lost. What I am after is reading in a line from a text file, that represents a type of hardware, the power consumption of the hardware and how long its left on for the last two may figures of data may also change, how would I go about doing this? As what I have at the moment to be honest is a complete mess :(

private void button1_Click(object sender, EventArgs e)
{
string lineReadFromFile;
StreamReader fileReader = null;

fileReader = new StreamReader("hardware.txt");

lineReadFromFile = fileReader.ReadLine();

while (lineReadFromFile != null)
{
string[] stringBits = lineReadFromFile.Split(new char[] { ',' });

for (int count = 0; count < stringBits.Length; count++)
{
hardware = stringBits[count].Split(new char[] { ' ' });

for (int position = 0; position < hardware.Length; position++)
{

}


textBox2.Text = textBox2.Text + hardware[count] + " \r\n";

}

lineReadFromFile = fileReader.ReadLine();

}



fileReader.Close();
}
 
Could you post a few lines from the file so we can see the format? Is there a separator between each piece of data on the line?

I would access the file in a using { } block so that I won't have to close the streamreaders etc after the file reading is complete. An array would also be useful to store each part of the line if there is a separator.

Something like below if a tab was the separator.

Code:
string myLine;
using (StreamReader reader = New StreamReader("myFile.txt"))
{
    while ((myLine = reader.ReadLine()) != null) {
    string items[] = myLine.Split('\t');

    //process the items from your line
    }
}

Edit: What are you going to do with the data when you read it in?
 
Last edited:
Could you post a few lines from the file so we can see the format? Is there a separator between each piece of data on the line?

I would access the file in a using { } block so that I won't have to close the streamreaders etc after the file reading is complete. An array would also be useful to store each part of the line if there is a separator.

Something like below if a tab was the separator.

Code:
string myLine;
using (StreamReader reader = New StreamReader("myFile.txt"))
{
    while ((myLine = reader.ReadLine()) != null) {
    string items[] = myLine.Split('\t');

    //process the items from your line
    }
}

Edit: What are you going to do with the data when you read it in?

When the data has been read in, I need to separate it into like text boxes and perform calculations such as power consumption and footprint.
The data needs to be read in of a file, but the file can be in any format we wish, I was going with, "phone, 15, 9"

Thank you
 
What are the columns in the file, what calculation do you need to perform?

Do you need the resulting form/page to display something like this, where the square brackets are text boxes?

PHP:
Phone - Power Consumption [ 15 ] Time Left On [ 9 ]
TV    - Power Consumption [ 30 ] Time Left On [ 2 ]
PC    - Power Consumption [ 90 ] Time Left On [ 10 ]
....
Calculated Value 1 [ xxx ] 
Calculated Value 2 [ xxx ]
Calculated Value 3 [ xxx ]
...

Then what do you plan on doing with the data? Is it just a case of read, calculate and display?

Is this a web app or win forms?
 
Last edited:
What are the columns in the file, what calculation do you need to perform?

Do you need the resulting form/page to display something like this, where the square brackets are text boxes?

PHP:
Phone - Power Consumption [ 15 ] Time Left On [ 9 ]
TV    - Power Consumption [ 30 ] Time Left On [ 2 ]
PC    - Power Consumption [ 90 ] Time Left On [ 10 ]
....
Calculated Value 1 [ xxx ] 
Calculated Value 2 [ xxx ]
Calculated Value 3 [ xxx ]
...

Then what do you plan on doing with the data? Is it just a case of read, calculate and display?

Is this a web app or win forms?

The columns, sorry are pretty much what you said, it is just a case of calculating and display for a win form

Thank you
 
The columns, sorry are pretty much what you said, it is just a case of calculating and display for a win form

Thank you

OK.

Create a new class to hold your data. Something like

PHP:
public class HardwareInfo
{
    public string Name { get; set}
    public int PowerConsumption { get; set; }
    public int TimeOn { get; set; }
}

You can also use this class to calculate derived values by amending it some thing like this

PHP:
public class HardwareInfo
{
    public string Name { get; set}
    public int PowerConsumption { get; set; }
    public int TimeOn { get; set; }

    public int DerivedValue
    {
        get
        { 
             return this.PowerConsumption * this.TimeOn;
        }
    }
}

Then use the pretty much the same code already mentioned by AMMUT

But use the loop to populate a collection of objects of your new HardwareInfo class type i.e

PHP:
// Hardware info collection
List<HardwareInfo> allHardwareInfo = new List<HardwareInfo>();

string myLine;
using (StreamReader reader = New StreamReader("myFile.txt"))
{
    while ((myLine = reader.ReadLine()) != null) {
    string items[] = myLine.Split('\t'); // It's important you replace '\t' with your delimiter

    var hardwareInfo = new HardwareInfo();
    hardwareInfo.Name = items[0];
    hardwareInfo.PowerConsumption = int.Parse(items[1]);
    hardwareInfo.TimeOn = int.Parse(items[2]);

    allHardwareInfo.Add(hardwareInfo);
    }
}

The allHardwareInfo collection can then be bound to GridView control and you can configure the columns to render as text boxes if that is what you require. Visual Studio has a nice wizard/gui for doing this.
 
Last edited:
OK.

Create a new class to hold your data. Something like

PHP:
public class HardwareInfo
{
    public string Name { get; set}
    public int PowerConsumption { get; set; }
    public int TimeOn { get; set; }
}

You can also use this class to calculate derived values by amending it some thing like this

PHP:
public class HardwareInfo
{
    public string Name { get; set}
    public int PowerConsumption { get; set; }
    public int TimeOn { get; set; }

    public int DerivedValue
    {
        get
        { 
             return this.PowerConsumption * this.TimeOn;
        }
    }
}

Then use the pretty much the same code already mentioned by AMMUT

But use the loop to populate a collection of objects of your new HardwareInfo class type i.e

PHP:
// Hardware info collection
List<HardwareInfo> allHardwareInfo = new List<HardwareInfo>();

string myLine;
using (StreamReader reader = New StreamReader("myFile.txt"))
{
    while ((myLine = reader.ReadLine()) != null) {
    string items[] = myLine.Split('\t'); // It's important you replace '\t' with your delimiter

    var hardwareInfo = new HardwareInfo();
    hardwareInfo.Name = items[0];
    hardwareInfo.PowerConsumption = int.Parse(items[1]);
    hardwareInfo.TimeOn = int.Parse(items[2]);

    allHardwareInfo.Add(hardwareInfo);
    }
}

The allHardwareInfo collection can then be bound to GridView control and you can configure the columns to render as text boxes if that is what you require. Visual Studio has a nice wizard/gui for doing this.

Thank you every so much for that help, however, I am still stuck

Project

What I'm having trouble to do is, how do I edit the values and save them? Preferably I'd like to save them to the file but I've spent most of the day on it just getting no where and completely confused :(

Thanks Mat
 
Thank you every so much for that help, however, I am still stuck

Project

What I'm having trouble to do is, how do I edit the values and save them? Preferably I'd like to save them to the file but I've spent most of the day on it just getting no where and completely confused :(

Thanks Mat

Is this for A Level course work? :)

You shouldn't create a class for each hardware type unless you need the collection to be polymorphic in which case it gets a little more complicated.. You should use the same class for all and hold the instances in a collection like in my example.

i.e. var List<HardwareInfo> allHarwareInfo = new List<HarwareInfo>();

If you bind the collection to a GridView the values are automatically updated in memory when you edit the cells in the GridView. Then when you're ready to save you can then loop back through the collection and save it to the file line by line in a reverse of how you read it in.

If your really struggling and I can send you a working example but it will cost ya :p
 
Last edited:
Is this for A Level course work? :)

You shouldn't create a class for each hardware type. You need to use the same class for all and hold the instances in a collection like in my example.

i.e. var List<HardwareInfo> allHarwareInfo = new List<HarwareInfo>();

If you bind the collection to a GridView the values are automatically updated in memory. Then when you're ready to save you can then loop back through the collection and save it to the file line by line in a reverse of how you read it in.

If your really struggling and I can send you a working example but it will cost ya :p

Nahhhh, its not course work its one from a while ago that I wanted to have a go at but I'm stuck. Thank you for the offer :L but I'll have to pass

Thankss
Mat
 
Is this for A Level course work? :)

You shouldn't create a class for each hardware type unless you need the collection to be polymorphic in which case it gets a little more complicated.. You should use the same class for all and hold the instances in a collection like in my example.

i.e. var List<HardwareInfo> allHarwareInfo = new List<HarwareInfo>();

If you bind the collection to a GridView the values are automatically updated in memory when you edit the cells in the GridView. Then when you're ready to save you can then loop back through the collection and save it to the file line by line in a reverse of how you read it in.

If your really struggling and I can send you a working example but it will cost ya :p

I've implemented your way of dealing with the class and how to display them in the combo box, but how do I get the other values to bind to the text box's :S I don't know if the answer is really obvious and I'm staring it right in the face cause I've been looking at it too long or what :L :(
 
I've implemented your way of dealing with the class and how to display them in the combo box, but how do I get the other values to bind to the text box's :S I don't know if the answer is really obvious and I'm staring it right in the face cause I've been looking at it too long or what :L :(

You bind the entire collection to a DataGridView control. Or if you wish to show the records one by one you can use a BindingNavigator. What is the combo box for?

In a simple situation like yours you shouldn't need any custom controls or binding logic. The standard win forms controls should be more than adequate.

Can you post your code again.
 
You bind the entire collection to a DataGridView control. Or if you wish to show the records one by one you can use a BindingNavigator. What is the combo box for?

In a simple situation like yours you shouldn't need any custom controls or binding logic. The standard win forms controls should be more than adequate.

Can you post your code again.

Project

So I want to be able to display those values in the text boxes, so I can calculate the values shown on the right of the form. Also, I'm sorry to keep asking for help but how would I also go about editing these values if needs be through the form and saving them back to the file if needs be?
 
The first thing you're missing is the concept of data binding.

Where you're doing

PHP:
// Populates the combo box with hardware types 
List<HardwareInfo> allHardwareInfo = new List<HardwareInfo>(); 

        string myLine; 

        using (StreamReader fileReader = new StreamReader("hardware.txt")) 
        { 
            while ((myLine = fileReader.ReadLine()) != null) 
            { 
                string [] items = myLine.Split(new char[] { ',' }); 

                var hardwareInfo = new HardwareInfo(); 

                hardwareInfo.Name = items[0]; 
                hardwareInfo.PowerConsumption = double.Parse(items[1]); 
                hardwareInfo.TimeOn = double.Parse(items[2]);
                hardwareInfo.Cost = double.Parse(items[3]);
                hardwareInfo.Co2 = double.Parse(items[4]);

                allHardwareInfo.Add(hardwareInfo);

                // This shouldn't be here
                cboHardware.Items.Add(items[0]);
            } 
            
            fileReader.Close();
        }

what you should be doing is actually not just populating the combo box with hardware types but loading the file data into a reusable collection.

The normal pattern for doing this in simple apps is something like this.

First create a method to fetch your data. This is usually from a database but it your case it's a file.

PHP:
public List<HardwareInfo> GetHarwareData()
        {
            // Populates the combo box with hardware types 
            List<HardwareInfo> allHardwareInfo = new List<HardwareInfo>();

            string myLine;

            using (StreamReader fileReader = new StreamReader("hardware.txt"))
            {
                while ((myLine = fileReader.ReadLine()) != null)
                {
                    string[] items = myLine.Split(new char[] { ',' });

                    var hardwareInfo = new HardwareInfo();

                    hardwareInfo.Name = items[0];
                    hardwareInfo.PowerConsumption = double.Parse(items[1]);
                    hardwareInfo.TimeOn = double.Parse(items[2]);
                    hardwareInfo.Cost = double.Parse(items[3]);
                    hardwareInfo.Co2 = double.Parse(items[4]);

                    allHardwareInfo.Add(hardwareInfo);
                }

                fileReader.Close();
            }

            return allHardwareInfo;
        }

Then in the form constructor you can load the data into a class level field.

e.g.

PHP:
private List<HardwareInfo> allHardwareInfo;

        public Form1()
        {
            InitializeComponent();

            this.allHardwareInfo = this.GetHarwareData();
        }

You can then use the class level field to "bind" to form controls.

Which in the case of your combo box it would be something like

PHP:
private void BindHardwareCombo()
        {
            BindingSource hardwareInfoSource = new BindingSource();

            hardwareInfoSource.DataSource = this.allHardwareInfo;

            this.cboHardware.DataSource = hardwareInfoSource.DataSource;

            this.cboHardware.DisplayMember = "Name";
            this.cboHardware.ValueMember = "Name";
        }

You can call this method in the form load method.

This really just demonstrates the broader principle of data binding. You can now bind the allHardwareInfo Collection to a whole host of control types using an almost identical method i.e.

  • Create a binding source
  • Set the binding source DataSource property to your data.
  • Set the DataSource of the the control to match that of the binding source

I would read up binding to the DataGridView and/or using the BindingNavigator controls. Both of these will allow you to display the data in text boxes of sorts and the behavior can be modified to suite your needs.

The binding source method offers a number of advantages when navigating and displaying data. But one of the other key advantages is when you edit data in the controls it's still "connected" to the underlying data source i.e. the values are automatically updated in the "allHardwareInfo" collection.

So when your finished editing you data you can just call a SaveHardwareData() method and implement the code to write the data back to your file.
 
Last edited:
The first thing you're missing is the concept of data binding.

Where you're doing

PHP:
// Populates the combo box with hardware types 
List<HardwareInfo> allHardwareInfo = new List<HardwareInfo>(); 

        string myLine; 

        using (StreamReader fileReader = new StreamReader("hardware.txt")) 
        { 
            while ((myLine = fileReader.ReadLine()) != null) 
            { 
                string [] items = myLine.Split(new char[] { ',' }); 

                var hardwareInfo = new HardwareInfo(); 

                hardwareInfo.Name = items[0]; 
                hardwareInfo.PowerConsumption = double.Parse(items[1]); 
                hardwareInfo.TimeOn = double.Parse(items[2]);
                hardwareInfo.Cost = double.Parse(items[3]);
                hardwareInfo.Co2 = double.Parse(items[4]);

                allHardwareInfo.Add(hardwareInfo);

                // This shouldn't be here
                cboHardware.Items.Add(items[0]);
            } 
            
            fileReader.Close();
        }

what you should be doing is actually not just populating the combo box with hardware types but loading the file data into a reusable collection.

The normal pattern for doing this in simple apps is something like this.

First create a method to fetch your data. This is usually from a database but it your case it's a file.

PHP:
public List<HardwareInfo> GetHarwareData()
        {
            // Populates the combo box with hardware types 
            List<HardwareInfo> allHardwareInfo = new List<HardwareInfo>();

            string myLine;

            using (StreamReader fileReader = new StreamReader("hardware.txt"))
            {
                while ((myLine = fileReader.ReadLine()) != null)
                {
                    string[] items = myLine.Split(new char[] { ',' });

                    var hardwareInfo = new HardwareInfo();

                    hardwareInfo.Name = items[0];
                    hardwareInfo.PowerConsumption = double.Parse(items[1]);
                    hardwareInfo.TimeOn = double.Parse(items[2]);
                    hardwareInfo.Cost = double.Parse(items[3]);
                    hardwareInfo.Co2 = double.Parse(items[4]);

                    allHardwareInfo.Add(hardwareInfo);
                }

                fileReader.Close();
            }

            return allHardwareInfo;
        }

Then in the form constructor you can load the data into a class level field.

e.g.

PHP:
private List<HardwareInfo> allHardwareInfo;

        public Form1()
        {
            InitializeComponent();

            this.allHardwareInfo = this.GetHarwareData();
        }

You can then use the class level field to "bind" to form controls.

Which in the case of your combo box it would be something like

PHP:
private void BindHardwareCombo()
        {
            BindingSource hardwareInfoSource = new BindingSource();

            hardwareInfoSource.DataSource = this.allHardwareInfo;

            this.cboHardware.DataSource = hardwareInfoSource.DataSource;

            this.cboHardware.DisplayMember = "Name";
            this.cboHardware.ValueMember = "Name";
        }

You can call this method in the form load method.

This really just demonstrates the broader principle of data binding. You can now bind the allHardwareInfo Collection to a whole host of control types using an almost identical method i.e.

  • Create a binding source
  • Set the binding source DataSource property to your data.
  • Set the DataSource of the the control to match that of the binding source

I would read up binding to the DataGridView and/or using the BindingNavigator controls. Both of these will allow you to display the data in text boxes of sorts and the behavior can be modified to suite your needs.

The binding source method offers a number of advantages when navigating and displaying data. But one of the other key advantages is when you edit data in the controls it's still "connected" to the underlying data source i.e. the values are automatically updated in the "allHardwareInfo" collection.

So when your finished editing you data you can just call a SaveHardwareData() method and implement the code to write the data back to your file.

I'm so sorry to keep bothering you but I'm not entirely sure I understand what you mean, this is what I have so far, how do I get the rest of the data to be displayed in the other text boxes?
 
I took a different approach to it and got the data from a database. This is what I have right now. My new problem is, how would I go about editing /adding new entities to it? This is another entirely new concept to me :(
 
Take a look at this.

Click File -> Download to get the rar file

I've tried to keep it simple so you can finish is off yourself and understand how it all works.

EDIT: not sure i've made te file public. I'll sort it in a bit

Thank I got it, and I've finished being able to edit the files :D Your help has been great. I have just one last question, is my formulas right?
 
Last edited:
I would say if you have a problem, it will be here:

Code:
costperitem = (powerUsed * timeLeftOn / 1000 * cost)

This can be interpreted in a few ways, you should add brackets to ensure that you calculate it the way you want. Some examples below.

Code:
costperitem = ((powerUsed * timeLeftOn) / (1000 * cost))
or
costperitem = (((powerUsed * timeLeftOn) / 1000) * cost)
 
I would say if you have a problem, it will be here:

Code:
costperitem = (powerUsed * timeLeftOn / 1000 * cost)

This can be interpreted in a few ways, you should add brackets to ensure that you calculate it the way you want. Some examples below.

Code:
costperitem = ((powerUsed * timeLeftOn) / (1000 * cost))
or
costperitem = (((powerUsed * timeLeftOn) / 1000) * cost)

According to that formulae it costs £1.70 to leave a server on all year, surely this cannot be right? :S
 
Back
Top Bottom