Changing the datasource in a DataGridView after cell editing
Please could anyone point me in the right direction for the reentrant exceptions I'm getting when I try and change the datasource of a DataGridView control. Below is a cut down example of the problem that I am currently unable to find a suitable solution for. I come from a Visual Foxpro background where this sort of thing is easily possible.
The only way I've partially solved this is by running a thread to update the datasource but because this is asynchronous there is a small chance that the update will not happen. Another way that works is to have a separate button control to reorder the data but this involves the user pressing it - a much better way would be to automate it after the cell update.
I understand why t开发者_开发百科he grid gets upset on changing a datasource when editing data of another source. I also know that the DataGridView can be set to sort on columns but I want to do more than just sort in my full version.
To run the code below add a DataGridView (naming it dgv1) to a form. Then to make the exception happen change the cell that has the 9 in to a 3 and then move off the cell by either clicking another cell or using the arrow keys. If enter is pressed before highlighting another cell then the exception doesn't occur nor does the grid get reordered.
namespace dgv_test
{
public partial class Form1 : Form
{
private List<dv> grid;
public Form1()
{
InitializeComponent();
// this would be from a database
List<dv> data = new List<dv>
{
new dv{ desc="t1", order=1},
new dv{ desc="t2", order=2},
new dv{ desc="t3", order=9},
new dv{ desc="t4", order=4},
new dv{ desc="t5", order=5},
};
// in memory list
grid =
(from lu in data
orderby lu.order
select new dv
{
desc = lu.desc,
order = lu.order
}).ToList();
// grid list
dgv1.DataSource =
(from g in grid
orderby g.order
select new dv
{
desc = g.desc,
order = g.order
}).ToList();
// make description column readonly
dgv1.Columns[0].ReadOnly = true;
}
private void dgv1_CellLeave(object sender, DataGridViewCellEventArgs e)
{
// only update memory copy if order column changed
if (dgv1.CurrentCellAddress.X == 1 && dgv1.IsCurrentCellDirty)
{
// grid is in memory copy of grid data
grid.ElementAt(dgv1.CurrentCellAddress.Y).order = int.Parse(dgv1.CurrentCell.EditedFormattedValue.ToString());
rgrid();
}
}
// this is the function to update datagridview control
private void rgrid()
{
// query the in memory list from the database
var gx =
(from g in grid
orderby g.order
select new dv
{
desc = g.desc,
order = g.order
}).ToList();
// set the datagridview control with the newly ordered set
dgv1.DataSource = gx.ToList();
// do the same for the in memory list so that both are in alinement
grid = gx.ToList();
}
}
class dv
{
public string desc { get; set; }
public int order { get; set; }
}
}
Try moving your code to the CellValueChanged
event of the DataGridView and it should work fine.
精彩评论