Messed up DataGridView when adding row to sorted datagrid view
-
Wednesday, September 19, 2012 11:29 AM
I have a DataGridView bound to a database Table. Visual Studio created the grid and a binding navigator Toolstrip. Navigating, Insert, Delete are working fine...
BUT:
If I sort the grid by clicking on some column header, inserting a row is messing up the grid. The row index passed to the RowsAdded event handler is wrong. Its always the index of last row which was fine in unsorted mode before. In sorted mode I am editing the wrong row and see no chance to find out the index of the right one. However, all data bound columns are displayed correctly even though index is always the last row. The problem occurs with not data bound columns. In my case an image column depending on a data bound column. The image is always drawn in the last row. Thus ignoring sorting...
Here is what I am doing in the RowsAdded event handler:
for (int i = 0; i < e.RowCount; ++i) { DataGridViewRow row = dataGridView_Energietraeger.Rows[i + e.RowIndex]; object idObj = row.Cells[Column_Id.Index].Value; if (idObj is System.DBNull || idObj == null) { // set default values to all cells in new row... // set icon indicating ro/ rw mode - wrong row when sorted! row.ReadOnly = (bool)readonlyObj; SetIconCellImage(row); } else { object readonlyObj = row.Cells[Column_Readonly.Index].Value; if (!(readonlyObj is System.DBNull) && readonlyObj != null) { row.ReadOnly = (bool)readonlyObj; SetIconCellImage(row); // } } }Any hints? May be I did not understand logics of databinding and how to access rows and datasources. but I can't see my mistake yet. Thanks in advance... Holger
All Replies
-
Thursday, September 20, 2012 7:38 AMModerator
Hi Holger,
I think that is by design. If you need to automatically sort the column, you can implement the logic in CellValueChanged event handler.
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex == 0) { if (dataGridView1.SortOrder != SortOrder.None) { ListSortDirection dir = dataGridView1.SortOrder == SortOrder.Ascending ? ListSortDirection.Ascending : ListSortDirection.Descending; dataGridView1.Sort(Column1, dir); } } }
Best regards,Chester Hong
MSDN Community Support | Feedback to us
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
-
Thursday, September 20, 2012 2:23 PM
Hi Chester,
thanks for your effort!
Unfortunately it does not solve the problem...
May be I should explain my case a bit more:
There is a dataGridView with data bound columns and one not data bound column (an icon indicating read only/ read write state of the particular row).
When adding a row by the binding navigator Toolstrip, I fill in default values for all cells of the new row (RowsAdded event handler). The data bound columns get their values correctly. The value (this occult rw/ ro icon) for cell in the not bound column always goes to the last row - ignoring that the correct row isn't the last one because of sorting already applied. Also the row.Readonly property is set to the wrong row (always last row in grid).
Best regards,
Holger
-
Thursday, September 20, 2012 8:09 PM
one more remark:
To make things mor simple to understand: drop the icon column. My problem would be solved if the row.ReadOnly property would be set to the correct one (please refer to my code snippet above).
Best regards,
Holger
-
Wednesday, September 26, 2012 10:49 AMModerator
Hi Holger,
Sorry for late response..
Base on my experiece, if you need to maintain the value of unbound columns when the datagridview is sorted by bound column. You have to use the virtual mode. First you need to set the VirtalMode property to true.
You can save your cells value in unbound columns into a dictionary, like: (Suppose there is an int type key in database.)
Dictionary<int, string> dict = new Dictionary<int, string>();
When the cell in unbound columns need to display, the CellValueNeeded event handler is raised. You can set the relationship of unbound columns in dict in CellValuePushed and CellValueChanged event handler.
More details, you can see:
How to: Implement Virtual Mode in the Windows Forms DataGridView Control
Another way may be to use CellFormatting, but I haven't tried if the icon can be flickerring.
Best regards,
Chester Hong
MSDN Community Support | Feedback to us
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
-
Thursday, September 27, 2012 9:08 PM
Hi Chester,
I will have a look on implementing data grid view in virtual mode. I really do not appreciate this because I'll have to spend attention to something I figured basic functionality of a data grid view.
Also I am still not sure whether you really see the point of my question:
The row.ReadOnly property is not maintained when sorted. The Rows_added event gives me the wrong row index! The unbound column, the icon and stuff depends on this flag. If this would be set to the correct row index, everything would be alright. Since the row index given to Rows_added event handler always refer to the LAST row, I have no chance to set this flag to the correct row if the grid is sorted...
Please see the comment in my listing above.
Thanks for your effort
Holger
-
Thursday, September 27, 2012 9:42 PM
Hi Chester,
just tested your proposed solution.
Unfortunately it has no effect. The ReadOnly property of the added row is still not set to the correct row (always to the last one).
Thus the icon is not set correctly and (worse) the user may edit rows which should not be edited.
Best regards
Holger
-
Wednesday, October 03, 2012 9:06 PM
Holger, I just solved this exact issue. I haven't even updated my thread yet. lol
how are you doing your binding? Originally, I was doing dgv.DataSource = dt.DefaultView.
my dt is declared at class level initialized to Nothing, and in a user initiated method, i new it up and add items. To fix, I added a BindingSource, also at class level, also initialized to Nothing. Then in my method after I new up the dt, I new up the bs. Set bs.DataSource = dt.DefaultView, then set dgv.DataSource = bs
I dont know how you are adding the new rows, but i handle all my changes manually. So in my add routine, i do: dim newdr as datarow = dt.NewRow
then add whatever values to newdr then dt.rows.add(newdr)
heres the KEY piece:
bs.Position = bs.Find("someuniquefield", newdr!someuniquefield)
dgv.ClearSelection()
dgv.FirstDisplayedScrollingRowIndex = bs.Position
dgv.Rows(bs.Position).Selected = Trueso for you it would be
dim dgvRow as DataGridViewRow = dgv.Rows(bs.Position)
then do what ever you need with your dgvRow. ;-)
i dont use the RowsAdded event of the dgv.
Hope this helps!
the real JeZteR
Check out my Blog: Titan Blog
Check my unanswered questions: JeZteR's Unanswered Questions -
Friday, November 09, 2012 4:28 PM
If you want to avoid a mess in bound DatagridView during AddRow(), you have to handle Sort direction of DataGridView to Ascending.bool reorder = false; ListSortDirection direction = ListSortDirection.Ascending; SortOrder actOrder = dgvZak.SortOrder; DataGridViewColumn sortCol = dgvZak.SortedColumn; if (actOrder == SortOrder.Descending) { reorder = true; direction = ListSortDirection.Descending; dgvZak.Sort(sortCol, ListSortDirection.Ascending); } dsZakazky.ZakazkyRow drNew = dsZakazky.Zakazky.NewZakazkyRow(); // for typed Dataset //now you can Add the Row dsZakazky.Zakazky.Rows.Add(drNew); if (reorder) //cleanup dgvZak.Sort(sortCol, ListSortDirection.Descending); //set position in Grid dgvZak.CurrentCell = dgvZak.Rows[0].Cells[0];I spent two days to find a solution. Beside that the values in Row were changed during addition - related dataset.


