Hi all...

I wish to draw a table showing 3 columns of values and many many rows.
However, i cant seem to find any other functions other than datagrid in the design toolbox interface of C#. And since my data source is not from any serverbased source (My data are only from .dat files located in my hdd), I do not know if I can use Datagrid to draw the table. Is there other ways to draw a table in C# without using datagrid? Or if datagrid is necessary or more convenient, is it able to draw table with source not from any database server?

Thanks for any help rendered...

Recommended Answers

All 22 Replies

You can bind the Datagrid to arrays and other similar collections.
Which version of VS are you using? If you are using VS2005 try the DataList control, it is much better for your use and you can code tables in the templates

Hi... thanks for the prompt reply. I am using VS 2003. I always hear ppl talking about binding arrays to datagrid. But what does it mean? My interpretation is as follow:

1) Read the lines from a .dat file, and array them in a for loop.
2) Bind the array to datagrid.

Are the interpretations correct?

no need to for loop them, if you know the delimiter then you should be able to put them straight into an array.

But yes you are correct. Once you have an array just set the grid datasource to the array and then call Databind on the grid.

Just as a thought, i assume the dat file is using a table like structure but you want to save it to disk not a database? If so i would recommend creating a dataset or strongly typed dataset in memory and then call the dataset.save method. Then you can call the dataset.read method when you want it and just bind to the grid without the for loop array. It makes searching and filtering much better. You dont need a back end database with ADO.net that is why they split the datasets from the dataadapters.

Yar... This is the part where I still dun understand... The data in my dat file looks something like this... not sure if its considered tabulated in ur sense...

0.200000000000000 -2.37875208125654 8.89149068490176
-1.54197025525003 16.2138152889587
0.400000000000000 -4.70208506970166 4.29899513347179
-0.122473657392517 5.26563417238388
0.600000000000000 -3.03187141119321 2.43126498291564
2.31215252446100 2.36115158336993
0.800000000000000 -2.03440037807500 1.81884834226502
3.02219205908151 1.69348030208479
1.00000000000000 -1.38619954085957 1.66793974796465
3.12514005981756 1.56289427464707
1.20000000000000 -0.912740905303422 1.65747262601114
2.99337573569932 1.57345864038550
1.40000000000000 -0.541662311537761 1.67911333342461
2.75455516251473 1.61842316014211

There are many many rows to continue... These are only part of it. So does this affect what you mentioned?

it looks tabular to me... it has to be to go into a grid or the data you show wont make sense. Create a data table with the columns you want (there appears to be 5 in yours) Create a dataset and add the table to the dataset. Then you just need to bind the grid to the datatable. To save it then call dataset.writexml(datfilename.dat) as it doesnt have to be an xml extension though i would recommend it unless there are other requirements why you have to have a .dat file. You can also encrypt it if you want but that is outside of this post.

When you need the data just create a dataset again and call dataset.readxml(datfilename.dat) and bind it to your grid again.

Very simple for offline storage and other non database storage.

Erm sorry... I know my data needs to be go into a grid before it makes sense... But the .dat files are generated in runtime. How can I transfer them to a tabulated format (Data table) in runtime as well? This is the step I am confused. Initially I wanted to make the DataSource of the DataGrid as an array, since I already got a 2-D array out from the data from the .dat file. But then, seems that DataSource can only be of the following types:

A DataSource for a DataGrid can comprise of seven different types of Data sources. These are as follows:

• DataTable

• DataView

• DataSet

• DataViewManager

• Single dimensional array

• IList interface

• An object that implements the IListSource

Thus, I have a major problem here since my array is 2-D. That eliminates the possibility of using array to be used as the DataSource. How should I use other types as the DataSource then?

Sorry but i am a bit confused with your requirements. You say you have a 2d array but your example earlier shows a 1d array. There are thousands of different scenarios so instead of me guessing could you tell me what you are trying to achieve (which is different from saying how you are implementing it). I think you are taking data from somewhere, storing it, then reading it later to display it. I can then give you the best solution to implement it. I am still thinking the best way will be datasets and a grid but i am not sure of the information and how it got there in the first place.

Hope it makes sense.
Who inputs the data?
What is the data (in general not specifics)
Why were you using a 2d array? Was the data 2 tiered?

Let me know and i will get back to you later

Oh sorry sorry. Huge miscommunication... hehe...

  1. The data is input by the user who keys in some variables that will generate the data in the .dat files in runtime.

  2. The data in the .dat files are some variables used in Fluids dynamics. They consist of time, lift and drag coefficient. All are doubles in C sense. Another .dat file consists of X, Y values of the coordinate system for plotting points, and also the Vorticity and Stream Function value. All are in double too. This will be the .dat example I am reading and trying to put in DataGrid in the following program.

  3. Well... I am not really sure is it 2-D array. I all along thought its a 2-D array, because that guy who developed the code for this .dat files said so. Thats for convenience in plotting the data on a graph. In fact, according to him, two of such 2-D arrays are required. I havent get to this yet... So ignoring this at the moment. But however, I just read on a MSDN book on a similar case to mine, data that is similar to those being in a .txt format (Mine can open using notepad too). It uses the ReadLine method to read lines, split the numbers and immediately adds the new data row. Seems that this is what you mean by 1-D array? So, I followed the code to implement the thing. It should be correct, compilation no error, execute with no error too. But however, nothing appeared in the display window. Its totally blank.(My whole datagrid is maximized to fill the whole Form1 window). What can be the problem?

Below is the code relating the DataTable and DataGrid binding I did in my program:

public Form1()
    {
        //
        // Required for Windows Form Designer support
        //
        InitializeComponent();

        //Creates a new DataSet
        DataSet myDataSet = new DataSet();

        //Creates a new DataTable and adds it to the Tables Collection
        DataTable aTable = new DataTable("Table 1");
        myDataSet.Tables.Add("Table 1");

        //Creates and names the 4 columns data from file 2cylinintegers.dat and adds to Table 1
        DataColumn Column1 = new DataColumn("X value");
        DataColumn Column2 = new DataColumn("Y value");
        DataColumn Column3 = new DataColumn("Vorticity");
        DataColumn Column4 = new DataColumn("Stream Function");

        myDataSet.Tables["Table 1"].Columns.Add(Column1);
        myDataSet.Tables["Table 1"].Columns.Add(Column2);
        myDataSet.Tables["Table 1"].Columns.Add(Column3);
        myDataSet.Tables["Table 1"].Columns.Add(Column4);

        //Creates the StreamReader to read the file and a string variable to hold the output of the StreamReader
        StreamReader myReader = new StreamReader("Fluids1.dat");

        //Checks to see if the Reader has reached the end of the stream
        while (myReader.Peek()>-1)
        {
            //Reads a line of data from the data file
            string myString = myReader.ReadLine().Trim();

            //Uses Regex.Split method to create an array of strings that represents each entry in the line.
            string [] split = System.Text.RegularExpressions.Regex.Split(myString, "\\s+", RegexOptions.None);

            //Adds the array as a new DataRow to Table 1
            myDataSet.Tables["Table 1"].Rows.Add(split);
        }

    }

We can look at the 2d arrays later. Your code is almost there.
First, with your columns if you know they are going to be doubles then set the column data type as a double too.

Finally at the end instead of your line myDataSet.Tables["Table 1"].Rows.Add(split); use the following

DataRow theRow = myDataSet.Tables["Table 1"].NewRow();
theRow["X value"] = (decimal)split[0];
theRow["Y value"] = (decimal)split[1];
theRow["Vorticity"] = (decimal)split[2];
theRow["Stream Function"] = (decimal)split[3];
myDataSet.Tables["Table 1"].Rows.Add(theRow);

But thats just better code... your main problem is you didnt bind the dataset to the grid!!! Easy to miss but causes a problem after so much coding huh.

MyGrid.Datasource = myDataSet.Tables["Table 1"];

or MyGrid.DataMember = "Table 1";
myGrid.DataSource = myDataSet

If you use the second option always set the datamember name before binding the datasource otherwise you will bind twice and waste performance

Hope that gets you going.

However, i still think you could have just called myDataSet.SaveXML("mydatfile.dat")
then all you have to do is create a dataset, then call myDataSet.ReadXml("mydatfile.dat") and then bind it straight to the grid, no reading, no stream writers and readers, no anything but 2 lines of code.

You fill the table in the first place much the same way column by column .. row by row but that is the same as the dat file, only i suspect it will be easier too.

Let me know how you get on

Heh really thanks alot, man! Its really a big help when noobs like me gets valuable pointers (like missing the binding of datagrid to the dataset) and suddenly gets the whole program up. Especially so when I got a real close dateline to meet... Really thanks alot...

And yar... Luckily you provided the other means of writing the code... I am able to start with reading the other .dat file, which is quite disorganised (The data shown in note #5). And I managed to implement it! So happy! ^^

One problem however is that of the (decimal) thing. Upon compilation, the compiler says that : Cannot convert type 'string' to 'decimal'. I know this is because I havent changed the strings to decimal, as mentioned by your first sentence..."First, with your columns if you know they are going to be doubles then set the column data type as a double too."... But how do I do this? I implemented this code before the decimal converting code:

for(int i=0;i<=3;i++)
{
    double.Parse(split[i]);
}

Seems abit wrong, but I am not very sure how to correct it. Any pointers?

And your sentence..."However, i still think you could have just called myDataSet.SaveXML("mydatfile.dat") then all you have to do is create a dataset, then call myDataSet.ReadXml("mydatfile.dat") and then bind it straight to the grid, no reading, no stream writers and readers, no anything but 2 lines of code."... I definitely hope to do it as simple as possible... But without any reference and as a newbie to programming... this is all I can do... (Editing from book's examples or web examples). I will try to learn more about this after 2 more days... After my first trial presentation ends... Thanks for suggesting such a possible learning opportunity for me :)

Really Thanks A Lot!

Erm, I am now trying to implement row names to the left of the numbers. I read a website (http://www.syncfusion.com/FAQ/WindowsForms/FAQ_c44c.aspx#q896q), it said the following code is able to do this. However, when i compiled, it said the TopRow() is missing. How can I find this?

Below is the code he mentioned that can be used to write row names:

private void dataGrid1_Paint(object sender, System.Windows.Forms.PaintEventArgs e) 

    { 

        int row = TopRow(); 

        int yDelta = dataGrid1.GetCellBounds(row, 0).Height + 1; 

        int y = dataGrid1.GetCellBounds(row, 0).Top + 2; 



        CurrencyManager cm = (CurrencyManager) this.BindingContext[dataGrid1.DataSource, dataGrid1.DataMember]; 

        while(y < dataGrid1.Height - yDelta && row < cm.Count) 

        { 

            //get & draw the header text... 

            string text = string.Format("row{0}", row); 

            e.Graphics.DrawString(text, dataGrid1.Font, new SolidBrush(Color.Black), 12, y); 

            y += yDelta; 

            row++; 

        } 

    }

did you download the sample or copy his text? I just looked at it and the text was only a small part to illustrate the complex part of the paint event. Download the whole code sample and the TopRow function will be in there. I suspect it is grabbing the co ords of the column headers and starting under there for the paint.

Ok... I downloaded his sample and found the TopRow function. Sorry I missed out that part... Anyway, it still didnt work. Not too sure why. Maybe its because he uses oledb? Mine is sourced from dat file, so maybe cannot? I think I need to use another way to write the function dataGrid1_Paint. Any pointers on how to edit the following function?

private void dataGrid1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
    {
        int row = TopRow();
        int yDelta = dataGrid1.GetCellBounds(row, 0).Height + 1;
        int y = dataGrid1.GetCellBounds(row, 0).Top + 2;

        CurrencyManager cm = (CurrencyManager) this.BindingContext[dataGrid1.DataSource, dataGrid1.DataMember];

        while(y < dataGrid1.Height - yDelta && row < cm.Count)
        {
            //get & draw the header text...
            string text = string.Format("row{0}", row);
            e.Graphics.DrawString(text, dataGrid1.Font, new SolidBrush(Color.Black), 12, y);
            y += yDelta;
            row++;
        }
    }

And can help me take a look at my post note #11 as well? I have problems parsing my strings into double. Thanks.

Erm... If my datagrid is supposed to be inside the child window, and initially empty, and I want a button(button1) inside the Parent window to activate it to fill the table in the datagrid (inside the child window) with data, how should I write the class or method?

for post #14 -Which part didnt work? There is no mention of oledb in that code. If you just want to test the code then replace the first line int row = Toprow() with int row = 0 for now.
Which line is failing?
post # 11. What is the problem? What error are you getting?

for(int i=0;i<=3;i++)
{
double.Parse(split[i]);
}

is ok. The only problem with it is that there may not be values in the array. I would do for(int i=0; i < split.length; i++) or if the length is greater and you only want the first 4 then do a test to make sure each exists before the parse. The only other way it would fail would be that it is not a number. Error handling comes in here. Always always (always^1000) check your variables before performing anything on them.
Post #15 There are a number of ways. Always the best way is using an MVC pattern (Model View Controller) but i suspect in your case you dont have the time to learn and implement this. Though i recommend you make it your #1 priority when you finish this.
If the parent has the dat file then i would make a property (internal set if you can) in the child form that takes the datatable we created (or whatever you have made the grid source to be). Then in the child form on the set for the property just call the grid bind. So on your parent button click handler just get a reference to the child form and set the property. IF you want the child form to get the dat file and do the binding then create a method (again internal if you can) in the child form to do all the work, then again in your parent button handler just get a reference to the child form and call the method. Simple :)

Hi f1fan. Finally finished with my mid-semester presentation today. Though I forgot quite alot of things, everything went on quite smoothly. I was really glad you solved that datagrid thing for me. It really meant alot (to the lecturers) to have at least shown that I got the results tabulated in the Windows Application I did.

Post #14 : There are no indications of failure. No compilation or execution error. Just no row headers on the leftmost column. I tried your method of putting int row = 0 but then still nothing happened... Any other possibilities?

Post #11 : After seeing your idea of using split.length, it sparked another idea and I managed to parse it after creating another double array and parsing the values individually from the string array one by one (using the for loop earlier). Thanks man. You saved the day again!

Post #15 : Icic. Abit deep for me though its simple for you :P I dont even know how to get a reference to a child form... Anyway, I think there is some miscommunication here again... Let me clarify what I hoped to achieve here...

I have a data file (.dat). I created a datagrid in the child window (childwin). I sourced it and bind it to the array read from the data file in the child window. Everything regarding database is done in child window already. I placed it an event named Databaseforming. If I make the Databaseforming event to load upon child window loadup, the database will be filled. But I do not want this. So, I included the event handler but with no call of the event function at all. I wish the data to only start filling the database only when I click a button (button1) located in the Parent window (mainwin).

This is the situation. I am not sure if I am right about this... but the only idea I can think of is to add a statement in the event handler for the button1_click event in the parent window to activate the Databaseforming event in the child window. I feel that the statement I added is quite wrong. The statement I added to the button1_click event is as follow:

childwin.Databaseforming(sender, (System.EventArgs) e);

The compilation error statement is as follow:

"An object reference is required for the nonstatic field, method, or property 'Testing.childwin.Databaseforming(object, System.EventArgs)' "

What can be the problem?

By the way, Really thanks alot... f1fan... I was implementing only one improvement to my program every 3-5 days for the past few months till I started asking in forums... but seldom people will reply as enthusiastic and helpful as you... Now, I can implement improvements almost everyday! Really thanks... much thanks...

ok not quite the way to go about it but would work. First some good programming standards advice - NEVER code in an event handler (eg button click event). Code in a method and call that method from your event handler. Why? Because it is reuseable and a lot more maintainable. It would also help you in this case.

So lets say you had your dataloading method
internal void LoadDataGrid(parameters)
{
}

we made it internal for a reason as you will see in a minute.
You can call that at anytime in your form (form load, form activate, some refresh button, just because its 3:30pm on Friday 13th... anytime not just in an event handler).

OK to call it from your parent window. At some time your parent window created a reference to the child window to show it (somewhere you have in youre code childwin mychildwin = new childwin(); mychildwin.show();

in your parent form button click event handler you need to code the following line
mychildwin.LoadDataGrid();
The important point here is that mychildwin is an INSTANCE of the childwin form and it is the SAME instance as the one that is showing currently. So you have to keep that instance in memory somewhere. Depending on how you called the childwin in the first place you have a few options: it could already be in your parents forms controls (if it was a subform, an mdi child etc.) or you have to manually add it to a class level variable just before calling the show event. All depends how many you instances of one form you are dealing with and how many different types of forms there are.

Remember: A form is just another type of class. It just happens to have a visual element but that is because someone nice at microsoft did some GDI+ stuff for you in their class (in the old days before they preceded everything with the word VISUAL we had to do it ourselves)

Sorry... Still not very sure about ur points...

1) In ur code:

internal void LoadDataGrid(parameters)
{
}

The parameters meant what? in my case, I onli filled the datagrid with the data from the datasource (.dat files) inside the method. So i assume the parameters is just ()?

2) Hrm I just want to data to fill that particular instance (activeview) of the childwin. Yar, there can be many child windows (mdichild) inside my parent window(mdi container). But there are various data variables specified in the parent window that can produce different data in the child window. So, each new child window means a new set of data. Not too sure about what you are talking about... So hope you can elaborate further after I explained this?

I was unsure of how your parent and child windows were related and also was giving a general way of achieving it instead of the specific code for your situation. But to answer your question. In your case the LoadDataGrid would have no parameters and from the mdi parent you would just call activemdichild.LoadDataGrid() when you needed it filled. Remember in the child windows to make the LoadDataGrid() internal so the mdi parent can call it

Ah icic. Same as what i did. Some errors though... I try solve myself. Its some kind of error I got from last time copy other ppl's mdichild format :P Must learn how he does the mdichild so that I can edit this time's problem :P Thanks first! :)

setting a form as an mdi container is one property on the form (IsMDIContainer). After that to set forms as mdi children when you instantiate a new form just set its MDIParent property to the parent instance. and all done.

The problem with blindly copying code is that you dont know what it is doing and therefore how to debug. By all means copy code to learn but do it in a seperate project and try to reproduce it so you understand it, and then try to expand/edit it so you fully understand it. Dont be fooled by the "i dont have time to do all that" thoughts as you are fast finding out that debugging takes a lot longer than coding and is 1000 times harder when you dont have a clue what it going on.
I would say a good programmer needs to be equally good at both coding and debugging (or possibly better at debugging) as i have yet to see someone code a real world program bug free on the first cut.

Hi all...

I wish to draw a table showing 3 columns of values and many many rows.
However, i cant seem to find any other functions other than datagrid in the design toolbox interface of C#. And since my data source is not from any serverbased source (My data are only from .dat files located in my hdd), I do not know if I can use Datagrid to draw the table. Is there other ways to draw a table in C# without using datagrid? Or if datagrid is necessary or more convenient, is it able to draw table with source not from any database server?

Thanks for any help rendered...

Hi!

You can use the DataGrid to draw the table, which you need is to load your data in a DataTable and this to use it in the DataSource property of the DataGrid.

PD: Sorry for my english

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.