WinForms Data Grid - How to avoid data conflicts when users drag cards of a TileView connected to a SQL source
When you drag-and-drop cards of a TileView connected to a SQL data source, a record index collision may occur. Moving a card marks the data source record as "to be removed", and a new record (with an updated data source index) is created instead. The previous record is not removed. As a result, the data row is duplicated.
This example shows how to avoid this issue. Create a column in the data source to store the position of cards within their groups. Update the position of a card every time the user drags the card.
// Sort by the "IndexInGroup" column
colIndexInGroup.SortOrder = DevExpress.Data.ColumnSortOrder.Ascending;
tileView1.BeforeItemDrop += TileView1_BeforeItemDrop;
void TileView1_BeforeItemDrop(object sender, BeforeItemDropEventArgs e) {
e.Handled = true;
// Leave data source indexes as is
e.NewListSourceRowIndex = e.ListSourceRowIndex;
var view = sender as TileView;
var column = view.Columns["IndexInGroup"];
/* Assign new IndexInGroup column values for all cards
that are already in the target group */
if(e.NewGroupRowHandle != GridControl.InvalidRowHandle) {
int childRowCount = view.GetChildRowCount(e.NewGroupRowHandle);
for(int n = 0; n < childRowCount; n++) {
int rowHandle = view.GetChildRowHandle(e.NewGroupRowHandle, n);
// Skip the TargetIndexInGroup - this index must belong to the dragged card
int index = n >= e.TargetIndexInGroup ? n + 1 : n;
view.SetRowCellValue(rowHandle, column, index);
}
}
// Assign the TargetIndexInGroup value to the "IndexInGroup" cell of the dragged card
view.SetRowCellValue(e.RowHandle, column, e.TargetIndexInGroup);
// Assign the new "colGroupId" column value to the dragged card
view.SetRowCellValue(e.RowHandle, view.ColumnSet.GroupColumn, e.NewGroupColumnValue);
}
' Sort by the "IndexInGroup" column
colIndexInGroup.SortOrder = DevExpress.Data.ColumnSortOrder.Ascending
AddHandler tileView1.BeforeItemDrop, AddressOf TileView1_BeforeItemDrop
Private Sub TileView1_BeforeItemDrop(ByVal sender As Object, ByVal e As BeforeItemDropEventArgs)
e.Handled = True
' Leave data source indexes as is
e.NewListSourceRowIndex = e.ListSourceRowIndex
Dim view = TryCast(sender, TileView)
Dim column = view.Columns("IndexInGroup")
Assign new IndexInGroup column values for all cards
that are already in the target group
If e.NewGroupRowHandle <> GridControl.InvalidRowHandle Then
Dim childRowCount As Integer = view.GetChildRowCount(e.NewGroupRowHandle)
For n As Integer = 0 To childRowCount - 1
Dim rowHandle As Integer = view.GetChildRowHandle(e.NewGroupRowHandle, n)
' Skip the TargetIndexInGroup - this index must belong to the dragged card
Dim index As Integer = If(n >= e.TargetIndexInGroup, n + 1, n)
view.SetRowCellValue(rowHandle, column, index)
Next n
End If
' Assign the TargetIndexInGroup value to the "IndexInGroup" cell of the dragged card
view.SetRowCellValue(e.RowHandle, column, e.TargetIndexInGroup)
' Assign the new "colGroupId" column value to the dragged card
view.SetRowCellValue(e.RowHandle, view.ColumnSet.GroupColumn, e.NewGroupColumnValue)
End Sub
(you will be redirected to DevExpress.com to submit your response)