I have DataGridView which is bounded with a datatable. I fill this datatable from database. I have 2 buttons right next to the datagridview, Up and Down. the rows should move up and down based on whichever button i click. I understand there are many answers for the similar issues but they work if your gridview isnt bounded. I also have a sequence column which has numbers from 0 onwards. When the rows move up or down, the sequence should be fixed as well. For example, if i move row[12] up, the sequence of row[12] should update to row[11] and row[11] should move down and row[11] sequence becomes row[12]. (I'm sorry if this is confusing). I also have 2 event functions attached to up and down buttons as well.
Edit: The main goal of this gridview is that user can add new rows as well. So, along with the above information, if there are 5 rows with sequence 1 to 5, and the user adds another row with sequence 2. I can sort the rows but how do I make the origninal rows with sequence 2,3,4,5 shift down and change their sequence to 3,4,5,6?
private void moveRow(int position)
{
DataRow selectedDataRow = null;
DataRow newDataRow = null;
int sequence = -1;
int newSequence = -1;
DataGridViewRow selectedRow = dataGridView.SelectedRows[0];
sequence = (int)selectedRow.Cells[sequenceDataGridViewTextBoxColumn.Index].Value;
newSequence = sequence + position;
if (newSequence <= 0 || newSequence > dataGridView.Rows.Count)
{
return;
}
//below code doesnt work at all maybe cuz it isnt right
//How do i select the current row and the row at the new sequence?????
if (selectedDataRow != null && newDataRow != null)
{//below i try to assign sequences to the rows
selectedDataRow["Sequence"] = newSequence;
newDataRow["Sequence"] = sequence;
}
dataGridViewRed.Sort(dataGridViewRed.Columns[buildSequenceDataGridViewTextBoxColumn.Index], ListSortDirection.Ascending);// i sort it again based on sequence
dataGridViewRed.CurrentCell = dataGridViewRed.Rows[selectedRow.Index + position].Cells[buildSequenceDataGridViewTextBoxColumn.Index];//highlight the current selected cell
//below functions are the events attached to the buttons for up and down
private void UpBtn_Click(object sender, EventArgs e)
{
moveRow(-1);
}
private void DownBtn_Click(object sender, EventArgs e)
{
moveRow(+1);
}
There are definitely some loopholes in my explanation so please be kind. I will do my best to explain any confusions, if need be.
If your rows are bound, then following example is applicable for moving row up. Prober Bounding should take care about sorting the DataGridView on the screen. If you sorted it in the data bound source, then it should work without .Sort, I think (I didn't test that).
If the row numbering could be inconsistent (c#):
DataGridViewRow SelectedDataRow = ...;
if (SelectedDataRow.Index > 0)
{
DataGridViewRow PrevDataRow = DataGridView1.Rows(SelectedDataRow.Index - 1);
Int16 PrevSequence = PrevDataRow.Cells("Sequence").Value; // buffer the previous sequence
PrevDataRow.Cells("Sequence").Value = SelectedDataRow.Cells("Sequence").Value; // set previous sequence to selected
SelectedDataRow.Cells("Sequence").Value = PrevSequence; // set selected to previous
}
VB.NET:
Dim SelectedDataRow As DataGridViewRow = ...
If SelectedDataRow.Index > 0 Then
Dim PrevDataRow As DataGridViewRow = DataGridView1.Rows(SelectedDataRow.Index - 1)
Dim PrevSequence As Int16 = PrevDataRow.Cells("Sequence").Value ' buffer the previous sequence
PrevDataRow.Cells("Sequence").Value = SelectedDataRow.Cells("Sequence").Value ' set previous sequence to selected
SelectedDataRow.Cells("Sequence").Value = PrevSequence ' set selected to previous
End If
If the rownumbering is consistent (continuous 1 to N), then it can be simplified:
DataGridViewRow SelectedDataRow = ...;
if (SelectedDataRow.Index > 0)
{
DataGridViewRow PrevDataRow = DataGridView1.Rows(SelectedDataRow.Index - 1);
PrevDataRow.Cells("Sequence").Value = SelectedDataRow.Index + 1;
SelectedDataRow.Cells("Sequence").Value = SelectedDataRow.Index; // set selected to previous
}
VB.NET:
Dim SelectedDataRow As DataGridViewRow = ...
If SelectedDataRow.Index > 0 Then
Dim PrevDataRow As DataGridViewRow = DataGridView1.Rows(SelectedDataRow.Index - 1)
PrevDataRow.Cells("Sequence").Value = SelectedDataRow.Index + 1
SelectedDataRow.Cells("Sequence").Value = SelectedDataRow.Index ' set selected to previous
End If
The moving down is similar, just the condition takes into account a limit of number of rows.
While this worked for me in similar scenario, I usually don't use binding in such scenarios, I use a DataTable as a data mediator.
Up
if (dataGridView1.SelectedRows.Count == 1)
{
DataGridViewRow Row = dataGridView1.SelectedRows[0];
if (Row.Index > 0)
{
var Index = Row.Index;
var OldRow = (DataGridViewRow)Row.Clone();
for (int i = 0; i < OldRow.Cells.Count; i++)
OldRow.Cells[i].Value = Row.Cells[i].Value;
dataGridView1.Rows.RemoveAt(Index);
dataGridView1.Rows.Insert(Index-1, OldRow);
}
}
Down
if (dataGridView1.SelectedRows.Count == 1)
{
DataGridViewRow Row = dataGridView1.SelectedRows[0];
if (Row.Index < dataGridView1.Rows.Count-1)
{
var Index = Row.Index;
var OldRow = (DataGridViewRow)Row.Clone();
for (int i = 0; i < OldRow.Cells.Count; i++)
OldRow.Cells[i].Value = Row.Cells[i].Value;
dataGridView1.Rows.RemoveAt(Index);
dataGridView1.Rows.Insert(Index + 1, OldRow);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With