Drag and Drop Rows in Blazor TreeList
- 4 minutes to read
This article describes how to enable drag-and-drop operations in the DevExpress Blazor TreeList. You can reorder rows within the TreeList, move rows between components, and change the component hierarchy.
Set Up Drag and Drop Permissions
Use the following properties to enable drag and drop functionality:
- AllowDragRows
- Specifies whether users can start row drag-and-drop operations.
- AllowedDropTarget
- Specifies allowed drag-and-drop targets. Targets can include the current TreeList and other components (Grids and TreeLists).
The table below lists allowed operations for various property value combinations:
AllowDragRows | AllowedDropTarget | Allowed Operations[1] |
---|---|---|
Any | None |
- |
false |
Internal |
- |
false |
External , All |
Drop from external components |
true |
Internal |
Reorder |
true |
External |
Drop onto/from external components |
true |
All |
Reorder and drop onto/from external components |
Users can select multiple rows and move the entire selection in a single drag-and-drop operation. Ensure that the SelectionMode property value is Multiple
and enable at least one of the following UI selection methods:
- Set the AllowSelectRowByClick property to
true
to enable row selection by mouse clicks, tap gestures, and keyboard shortcuts. - Declare a DxTreeListSelectionColumn object in the Columns collection to display the selection column.
Update Data Sources
When a user drops rows, the target component’s ItemsDropped
event fires. In its handler, update the data source: insert rows at the drop position and remove them from the initial position, if required. You may need to call the Reload
method to apply data source changes. Refer to method descriptions for more information:
The DxTreeList.DropTargetMode property specifies drop position indication style for operations initiated externally:
BetweenRows
- Users can choose a specific drop position between two existing rows. TargetItem and DropPosition properties return information about this location.
Component
- Users drop rows onto the entire data area. You need to implement custom insertion logic (for example, if your data is sorted or grouped) in the ItemsDropped event handler.
Note
If you allow users to sort data, the data source arranges data items based on sort settings. The component cannot guarantee a specific drop position and automatically switches to the Component
mode.
Example
In the following example, the first TreeList inserts rows to a specific location; the second TreeList adds dropped rows after the last TreeList item:
<DxTreeList @ref="TreeList"
Data="PriorityTasks"
KeyFieldName="Id"
ParentKeyFieldName="ParentId"
AllowDragRows="true"
AllowedDropTarget="TreeListAllowedDropTarget.External"
ItemsDropped="FirstTreeList_ItemsDropped">
<Columns>
<DxTreeListDataColumn FieldName="Name" Caption="Task" SortOrder="TreeListColumnSortOrder.Ascending" />
<DxTreeListDataColumn FieldName="EmployeeName" Caption="Assigned To" TextAlignment="TreeListTextAlignment.Left" Width="200px" />
<DxTreeListDataColumn FieldName="StartDate" Width="100px" />
<DxTreeListDataColumn FieldName="DueDate" Width="100px" />
</Columns>
</DxTreeList>
<DxTreeList @ref="TreeList"
Data="PostponedTasks"
KeyFieldName="Id"
ParentKeyFieldName="ParentId"
AllowDragRows="true"
AllowedDropTarget="TreeListAllowedDropTarget.External"
DropTargetMode="TreeListDropTargetMode.Component"
ItemsDropped="SecondTreeList_ItemsDropped">
<Columns>
<DxTreeListDataColumn FieldName="Name" Caption="Task" SortOrder="TreeListColumnSortOrder.Ascending" />
<DxTreeListDataColumn FieldName="EmployeeName" Caption="Assigned To" TextAlignment="TreeListTextAlignment.Left" Width="200px" />
<DxTreeListDataColumn FieldName="StartDate" Width="100px" />
<DxTreeListDataColumn FieldName="DueDate" Width="100px" />
</Columns>
</DxTreeList>
@code {
ITreeList TreeList { get; set; }
ObservableCollection<EmployeeTask> PriorityTasks { get; set; }
ObservableCollection<EmployeeTask> PostponedTasks { get; set; }
void FirstTreeList_ItemsDropped(TreeListItemsDroppedEventArgs evt) {
if(evt.TargetItem == null)
return;
var droppedTask = (EmployeeTask)evt.DroppedItems[0];
PostponedTasks.Remove(droppedTask);
var targetTask = (EmployeeTask)evt.TargetItem;
droppedTask.ParentId = evt.DropPosition == TreeListItemDropPosition.Inside
? targetTask.Id
: targetTask.ParentId;
var index = PriorityTasks.IndexOf(targetTask) + (evt.DropPosition == TreeListItemDropPosition.After ? 1 : 0);
PriorityTasks.Insert(index, droppedTask);
}
void SecondTreeList_ItemsDropped(TreeListItemsDroppedEventArgs evt) {
if(evt.TargetItem == null)
return;
var droppedTask = (EmployeeTask)evt.DroppedItems[0];
PriorityTasks.Remove(droppedTask);
PostponedTasks.Insert(PostponedTasks.Count, droppedTask);
}
}
Customize Drag-and-Drop Hints
The drag hint displays the row preview if a user drags one row. If a user drags multiple rows, the hint displays the number of dragged rows.
Use the DragHintTextTemplate to define a custom message template for the drag hint. The custom template keeps predefined paddings and the drag handle icon.
The following example replaces the default text message:
<DxTreeList @ref="TreeList"
Data="DataSource"
KeyFieldName="Id"
ParentKeyFieldName="ParentId"
ItemsDropped="TreeList_ItemsDropped"
SelectionMode="TreeListSelectionMode.Multiple"
AllowSelectRowByClick="true"
AllowDragRows="true">
<Columns>
<DxTreeListDataColumn FieldName="Name" Caption="Task" SortOrder="TreeListColumnSortOrder.Ascending" />
<DxTreeListDataColumn FieldName="EmployeeName" Caption="Assigned To" TextAlignment="TreeListTextAlignment.Left" Width="200px" />
<DxTreeListDataColumn FieldName="StartDate" Width="100px" />
<DxTreeListDataColumn FieldName="DueDate" Width="100px" />
</Columns>
<DragHintTextTemplate>
@{
var taskCount = context.DataItems.Count();
}
<i>Selected tasks: @taskCount</i>
</DragHintTextTemplate>
</DxTreeList>
You can also use DragHint
and RowDragAnchorCell
element types in the CustomizeElement event handler to apply custom styles and attributes.