How to reuse DataTable for different data source in C#? - c#

I have a DataTable (displayed via a DataGridView) and want to reuse it to manually fill in different data. So the workflow is:
Every time I need to refill the DataTable, I do:
Unhook the DataTable from the DataGridView.
Clear DataTable content.
Manually add DataColumns and DataRows to the DataTable.
Hook the DataTable again with the DataGridView.
To achieve step 0, I simply do: DataGridView.DataSource = null.
To achieve step 1, I call DataTable.Clear(), DataTable.Rows.Clear() and DataTable.Columns.Clear().
To achieve step 3, I call DataGridView.DataSource = DataTable.
Step 2 is done in normal way and I skip the code.
Whenever the DataGridView is updated with a new content, if I click DataGridView column to sort, the next time when the DataTable is updated, I will get a null reference exception in step 2 when I try to add new rows. But if I never click DataGridView column to sort, all works fine.
I guess it has something to do with the sorting. But I have no idea what causes the null reference exception. Is it possible that the DataTable tries to search some keys in old content but couldn't find it? It cannot find the old content because of step 1 of course. What is the right way of clearing old DataTable content so it never refers the old content when I fill in new stuff?
Thanks.

The DataGridView's databinding is tied to the table (through a DataView); you cannot pull the table out from under it and expect it to continue working.
When you sort by a column, the grid asks the DataView to change its sort order, which fails because the column doesn't exist anymoe.
You should create a new DataTable.

Related

C# Commit changes in DataGridView to DataTable

I need an example of code or project with one DataGridView Form and one DataTable so I can edit DataGridView cells and then all the changes are automatically commited into the DataTable. Also how can I create DataTable with the same columns with DataGridView other way that manually?
I tried to create DataGridView and DataTable with the same columns manually and then set the DataGridView.DataSource = DataTable, but data saved into the table are null (anyway number of new rows is correct, but values are invalid).
Tried to google it - all the samples and questions are about savind into DataBase, but I don't need a DB, I just need a simple DataTable and DataGridView binding.
Thanks!
There's no way to create a table automatically from the DataGridView columns (EDIT To refine this: There are ways to automatically create database structures - ORM would be a good keyword here - but I guess that's not what you need). The other way round works well: Create the table and assign it to the DataGridView as its data source. Then the grid should show the respective columns.
"Storing" the values in the data table works only if you have "told" the columns, which field of the underlying table they relate to. That is: You need to create the table columns (it has a name), and when you create the DataGridView column, you need to assign the column name to the DataPropertyName property of the column.
Easiest way for you: Create a typed dataset (use the "Add to project" dialog to add a new "DataSet"), manually create a table in the dataset's designer, drag an instance of your dataset to the form and assign this as the data source to your DataGridView. Everything else should appear automatically.
I hope you this links from codeproject might help:
http://www.codeproject.com/Questions/80935/save-datagrid-data-to-database
http://www.codeproject.com/Articles/12846/Auto-Saving-DataGridView-Rows-to-a-SQL-Server-Data
If your DataTable is set as the DataSource for the dataGridView, the contents in the dataGridView will reflect the data in the DataTable and vice versa. Therefore, if you make changes to the dataGridView, those changes are already in the DataTable.
Convert DatagridView To DataTable.
In C#.NET:
DataTable dt = ((DataView)this.dataGridView1.DataSource).Table;
VB.NET:
Dim dt As DataTable = CType(Me.dataGridView1.DataSource,DataView).Table

Customise a bound datagridview

Howdy, using vs2008 winforms.
I want to be able to use a slightly customised datagridview but cant think of a way to do it.
i have
1. a sqldataadaptor fill a dataset
2. a binding source bound to the dataset
3 a datagridview with the bindingsource set as the datasource.
I want the binding to allow sync between the dataset and datagridview, so i can edit data and then update to database with sqldataadaptor. update.
I want to show some custom columns that are calculated results.
And i want to show a final bottom row that is totals of all the columns in the DVG.
My problem is once the DGV is bound i cant add a custom column or row, it wont let me.
I know i could add it directly to the dataset that is the underlying datasource but then by changing the structure of the dataset i cant update to a database once edits have taken place.
or can i ???
Can someone tell me how i can add my custom columns and a final total row to a bound DGV.
Also while im here, if i click on the top of a column to sort on it, in a bound DGV, will it also re-sort the underlying dataset, so i i edit things will still stay synced ?
thanks in advance for any help
Yes, you can.
The adapter does not care about structure. It only cares about column names used in the Select/Insert/Update/Delete commands. You can add custom columns, expression columns, columns for subtotals, columns for totals, or whatever you need. Even change the order of the columns. I do advise adding a sort column, so you can keep the custom rows in the proper place when you or the user sorts.
You can do the same thing for custom rows. When you update through the adapter, you handle the RowUpdating event and set the SqlRowUpdatingEventArgs.Status to SkipCurrentRow for these custom rows. I strongly advise creating a row type column so you know which rows to skip when updating. (You can also use the sort column's value as a key to skip rows.)
There are a couple of articles on MSDN or KB that illustrate how to add total rows.
"How to sum the fields in a Windows Forms DataGrid control and then display the calculated totals in a footer by using Visual Basic .NET" at http://support.microsoft.com/kb/836672.
In my experience, manipulate the data table first before binding. Do what you need to do in order to support the grid and the grid's interface. It is okay to manipulate the data, add/change/remove columns and rows, then rebind when needed.
To be able to add additional unbound columns to your DataGridView you could also set its AutoGenerateColumns property to false and then add custom columns with the following method:
dataGridView->Columns->Add(...)
To calculate the contents of the unbound columns you can handle the CellValueNeeded and CellValuePushed events but you must set the DataGridView into 'virtual mode' by setting the VirtualMode property to true in order for the eventhandlers to be invoked.
Hope this helps a little....

Moving to specific record within a DataTable

Hopefully simple, but can't find any such option.
I have a data table -- has say... 10 rows in it. Some fields on the form are bound to the table.columns respectively by name.
On another form that HAS a grid, as I scroll the grid, the detail fields are refreshed as expected since the grid does some magic to trigger the DataTable record changing event.
WITHOUT using a Data Grid, How can I direct the table to go to a specific row for load/display refresh on the form... ex:
DataTable MyTable = new DataTable();
MyTable = GetResultsFromSQL(); // returns the 10 rows
MyTable.LoadTheDataForRow(3);
MyTable.LoadTheDataForRow(7);
MyTable.LoadTheDataForRow(2);
I know I can use a foreach row in the table, but need explicit use as I don't want to go through all rows, but need specificity to specific ones.
I've looked at the LoadDataRow(), but that appears to be for pushing data back to a server. NOT what I want... I just want to have the "Current" row of the table to be of a specific one...
Thanks
After further research, I've found that a FORM based control "BindingSource" (or derivative) allows this, such as a grid. But, obviously, there's something the .Net engine is doing under the hood to ultimately "Load" a given row into something that ultimately triggers back to the "BindingSource"... The DataTable has RowChanging and RowChanged events which appear to be triggered by OnRowChanging / OnRowChanged delegates, but how can we tell the data table which "row" we want it as the active one.
The form controls can do this for their binding sources, but what is really happening under the hood to trigger these OnRowChanging events... I don't want to re-load a data table, rows, etc, just change what is considered the "Active" row, as in a grid, listbox, combobox, etc.
Have you tried:
MyDataTable.Rows[3];
MyDataTable.Rows[7];
MyDataTable.Rows[2];

Directly manipulating a DataSet

I have a lightweight data-basey kind of thing. Functionally, I'd like to read and write tables out to disk(plus maybe some other info in the future).
I chose to use the DataSet object, paired with the DataGridView control for the IO. The DataSet object can serialize out to disk and back again via the handle XML read/write functions.
However, there does not seem to be an obvious way to add information to the DataView control and have the DataSet object updated. Among other things, the DataGridView won't add a row for me in run-time and won't let me programmatically run the addrow method.
Clearly, I'm missing something.
What am I missing?
This has been suggested:
dataSet1.Tables["mytable"].Rows.Add();
But System.Data.DataRow does not permit direct construction, and I want to add a blank row for the DataGridView to fill in?
edit2: I'm dumb. There's a new row function.
Hmm. I'm wondering if this is just a Wrong Approach.
Don't modify the content of the DataGridView programmatically, modify the DataSet itself instead. It will automatically update the DataGridView if it is databound to the DataSet (using the DataSource and DataMember properties). Changes made by the user in the DataGridView will be automatically reflected in the DataSet.
UPDATE
dataSet1.Tables["mytable"].Rows.Add();
But System.Data.DataRow does not permit direct construction, and I want to add a blank row for the DataGridView to fill in?
You can construct a DataRow manually :
DataRow row = dataSet1.Tables["mytable"].NewRow();
row["column1"] = value1;
row["column2"] = value2;
...
dataSet1.Tables["mytable"].Rows.Add(row);
If you just want a blank row, just don't initialize the fields...
If you have a BindingSource between the DataSet and the DataGridView, call AddNew on the BindingSource. It will add a blank line. You can also use a BindingNavigator control, which handles the calls to the BindingSource methods.

How do I create a DataGrid in C#?

I want to add a DataGrid to a Form. When the program executes, the user enters values and I use those values in the problem. I need a similar implementation for a table with two columns and when the user enters values I use them to for calculation in the program.
There is no requirement to save these values to a database, they are just going to be used in the program.
How do I do this in C#?
In a winforms environment, you can bind strongly typed collections as the datasource; Each property of the objects in the collection makes a column (Strictly speaking, I believe it works out the properties for the type that the collection returns, rather than the individual items in it)
If you are writing a WinForms App then you can use a DataTable to store the data and a DataGridView to display it. Simply create the DataTable:
dataTable = new DataTable();
Create the columns you need programatically:
var columnSpec = new DataColumn();
columSpec.DataType = typeof(decimal); // If it holds a decimal
columSpec.ColumnName = "Interest Rate";
dataTable.Columns.Add(columnSpec);
Add the DataGridView to the form using the Designer - but don't and then once the table has been created bind it to the grid using:
dataGridView.DataSource = dataTable;
You can set the properties on the grid from the designer view.
I have done this in a read-only case where the DataTable is populated from the program and just displayed it. All the user can do is resize, reorder or set the visibility on the columns. To add new rows you'll need to hook into the RowsAdded event
Re-wording Rowland Shaw
You need not have a database to bind to the datagrid. If you have the data filled in a strongly typed or a generic collection you can bind the datagrid to the collection. The datagrid will fill the data from the collection.
It will take the property names as the columns, and the rows will display as per the rows in the collection.
If you want user input, then I think you should consider using a better grid control. The datagrid is not suitable for this purpose. I dont' remember if flexgrid (the ocx one) has been redone for .Net.
You can use a datagridview and build a datatable and add columns through your code and set the datatasource of your datagridview as this datatable and set AllowUserToAddRows in properties window of Dataggridview to true ( true is the default value ).
If you want to make the calculation after a full ro update is made then you can use RowPrePaint event or if you want the calculation to be made after the data in each cell gets updated then you can use the CurrentCellChanged event of the datagridview.
Hope this helps....

Categories

Resources