views:

813

answers:

5

say I display a datatable on a datagridview, then the user sorts it, and selects a row... I want to do something with the original datatable to the same row... but the row indexes in the datagridview and datatable are now out of sync. How should I be doing this?

A: 

If your table has a primary key, get it from the selected row, then use the DataTable.Select() method to locate that row in the datatable.

Matthew Jones
the data is now in a datagridview so I wouldn't be able to use datatable.select(), can you tell me more about how this would work?
Maslow
also no primary key is present on this datatable
Maslow
DataTable.Select() would use expressions to locate rows that match the criteria in the expression. You do not need a primary key to do this (however datatable does not store the row index, so that is not returned, but the actual row is). See the following page for an example. http://msdn.microsoft.com/en-us/library/det4aw50.aspx
Matthew Jones
dataTable.Select on a table with no primary key would seem to involve filtering by all the values, at that point I have the values and may as well just build an object or something? If I had a column with a hidden index value, select doesn't let me remove that column to pass back just the row without the new index.
Maslow
+1  A: 

Assuming that the source for the data has an index, you can store the index as a hidden column in your datagridview.

PJ8
and then traverse the entire table looking for that value?
Maslow
Can you assign a unique key to each record in your datatable before you load it into your datagridview? Then the index on the selected row would map to the index in your datatable.
PJ8
+1  A: 

A couple things come to mind.

  1. You can requery the DataTable's data source.

  2. You can programmatically add a Column to your DataTable that acts as an index of the DT's original row order. When you want to restore the sort order, sort on this column. I've done this. You can set the new Column's AutoIncrement property to true and the column's values will be filled in for you.

HTH

Jay Riggs
I can't see how I can requery the datatable's data source and still wind up with the row at position X from the datagridview. programmatically adding an index to the datatable as it comes in, may be viable, but seems like more overhead then should be needed for this simple operation.
Maslow
You can programmatically set the selected row in the DGV after you requery.
Jay Riggs
How can adding an index as it comes in be "more overhead than needed"? You need an index. Assuming you can't modify the datatable, adding an index when you load it is "exactly as much overhead as needed".
JPLemme
I was hoping and expecting that the DataGridView had a sourceIndex property or something like that for this very type of situation. Now that I've learned [System.ComponentModel.Browsable(false)] this solution becomes far more useful.
Maslow
This would have worked best were I not doing databinding now
Maslow
A: 

If I understand your question correctly, you are trying to match the row indices of the your DataTable with the sort order indices of your DataGridView. In the example below, the sort column name is "index".

'Apply a sort order to the gridview
table.DefaultView.Sort = "index ASC"

'Assign the datasource of DataGridView to DataTable
gridview.DataSource = table.DefaultView

'Change the index value of the DataTable which will cause
' the DataGridView to resort the view. In this case, swap rows 0 and 1.
table.Rows(0).Item("index") = 1
table.Rows(1).Item("index") = 0

Now the order of the rows in table has not been changed, only the gridview sorts and displays the new order of the rows.

The only way I know of, although it is not a great solution, is as follows:

'Reassign the DataTable to its own sorted DefaultView
table = table.DefaultView.ToTable()

'Reapply a sort order to the gridview
table.DefaultView.Sort = "index ASC"

'Reassign the datasource of DataGridView to DataTable
gridview.DataSource = table.DefaultView

Now both the table and the gridview have the same row order.

Please post a better solution if you know of one. Hope this helps.

Arun Thomas
A: 

I was working my butt off to avoid using databinding on a datagridview. now that I've figured that stuff out this isn't really a problem.

I still feel the datagridview should automatically have a sourceindex property for each datarow, but with

  • databinding
  • a layer of business objects in between the db and the datagrid
  • System.ComponentModel.Browsable(false) attribute

I can make the datagridviewRow hold a reference to the entire object itself, without it showing as a dataGridViewColumn

Maslow