Skip to main content
All docs
V24.2

DevExpress v24.2 Update — Your Feedback Matters

Our What's New in v24.2 webpage includes product-specific surveys. Your response to our survey questions will help us measure product satisfaction for features released in this major update and help us refine our plans for our next major release.

Take the survey Not interested

DxTreeList.ItemsDropped Event

Fires when a user drops rows onto the TreeList.

Namespace: DevExpress.Blazor

Assembly: DevExpress.Blazor.v24.2.dll

NuGet Package: DevExpress.Blazor

#Declaration

C#
[Parameter]
public EventCallback<TreeListItemsDroppedEventArgs> ItemsDropped { get; set; }

#Parameters

Type Description
TreeListItemsDroppedEventArgs

An object that stores event information.

#Remarks

The ItemsDropped event fires when users drop rows onto the TreeList (AllowedDropTarget). In the event handler, update the data source: insert rows at the drop position and remove them from the initial position, if required.

Note that the DroppedItems event argument contains rows in the order they are displayed in the component. If you enable virtual scrolling, the DroppedItems collection contains rows in the order they were selected.

In the following example, the Grid allows users to drag rows to external targets. The TreeList accepts rows from the Grid and allows row reordering:

Run Demo: Drag and Drop Rows - Between Components

Razor
<DxTreeList @ref="PlannedTasksTreeList"
            Data="PlannedTasks"
            KeyFieldName="Id"
            ParentKeyFieldName="ParentId"
            AllowDragRows="true"
            AllowedDropTarget="TreeListAllowedDropTarget.All"
            ItemsDropped="TreeList_ItemsDropped">
    <Columns>
        <DxTreeListDataColumn FieldName="Name" Caption="Task" />
        <DxTreeListDataColumn FieldName="Priority" Width="100px" CaptionAlignment="TreeListTextAlignment.Center" TextAlignment="TreeListTextAlignment.Center">
            <CellDisplayTemplate>
                @GetEmployeeTaskPriorityIconHtml((EmployeeTask)context.DataItem)
            </CellDisplayTemplate>
        </DxTreeListDataColumn>
    </Columns>
    <DragHintTextTemplate>
        @if(context.DataItems[0] != null) {
            var employeeTask = (EmployeeTask)context.DataItems[0];
            <span class="dxbl-text">@(employeeTask.Name)</span>
            <span class="dxbl-text">@GetEmployeeTaskPriorityIconHtml(employeeTask)</span>
        }
    </DragHintTextTemplate>
</DxTreeList>

<DxGrid Data="PendingTasks"
        TextWrapEnabled="false"
        AllowDragRows="true"
        AllowedDropTarget="GridAllowedDropTarget.External"
        ItemsDropped="Grid_ItemsDropped">
    <Columns>
        <DxGridDataColumn FieldName="Name" Caption="Task" />
        <DxGridDataColumn FieldName="Priority" Width="100px" CaptionAlignment="GridTextAlignment.Center" TextAlignment="GridTextAlignment.Center">
            <CellDisplayTemplate>
                @GetEmployeeTaskPriorityIconHtml((EmployeeTask)context.DataItem)
            </CellDisplayTemplate>
        </DxGridDataColumn>
    </Columns>
    <DragHintTextTemplate>
        @if(context.DataItems.Count == 1) {
            var employeeTask = (EmployeeTask)context.DataItems[0];
            <span class="dxbl-text">@(employeeTask.Name)</span>
            <span class="dxbl-text">@GetEmployeeTaskPriorityIconHtml(employeeTask)</span>
        }
        else {
            <span class="dxbl-text">@(context.DataItems.Count) tasks</span>
        }
    </DragHintTextTemplate>
</DxGrid>

@code {
    ITreeList PlannedTasksTreeList { get; set; }

    ObservableCollection<EmployeeTask> PlannedTasks { get; set; }
    ObservableCollection<EmployeeTask> PendingTasks { get; set; }

    protected override async Task OnInitializedAsync() {
        var employeeTasks = EmployeeTaskDataProvider.GenerateData();
        PlannedTasks = new ObservableCollection<EmployeeTask>(employeeTasks.Where(t => t.Priority <= 0));
        PendingTasks = new ObservableCollection<EmployeeTask>(employeeTasks.Where(t => t.Priority > 0));
    }

    void TreeList_ItemsDropped(TreeListItemsDroppedEventArgs evt) {
        var sourceTasks = GetTaskCollection(evt.SourceComponent);
        RemoveDroppedItems(sourceTasks, evt.DroppedItems);

        var targetTask = (EmployeeTask)evt.TargetItem;
        var index = targetTask != null
            ? PlannedTasks.IndexOf(targetTask) + (evt.DropPosition == TreeListItemDropPosition.After ? 1 : 0)
            : PlannedTasks.Count;

        var droppedTasks = evt.DroppedItems.OfType<EmployeeTask>();
        foreach(var droppedTask in droppedTasks) {
            droppedTask.ParentId = evt.DropPosition == TreeListItemDropPosition.Inside
                ? targetTask.Id
                : targetTask.ParentId;
        }

        InsertDroppedItems(PlannedTasks, evt.DroppedItems, index);
    }

    void Grid_ItemsDropped(GridItemsDroppedEventArgs evt) {
        var sourceTasks = GetTaskCollection(evt.SourceComponent);
        RemoveDroppedItems(sourceTasks, evt.DroppedItems);

        var targetTask = (EmployeeTask)evt.TargetItem;
        var index = targetTask != null
            ? PendingTasks.IndexOf(targetTask) + (evt.DropPosition == GridItemDropPosition.After ? 1 : 0)
            : PendingTasks.Count;

        InsertDroppedItems(PendingTasks, evt.DroppedItems, index);
    }

    void RemoveDroppedItems(IList<EmployeeTask> employeeTasks, IEnumerable<object> droppedItems) {
        foreach(var item in droppedItems)
            employeeTasks.Remove((EmployeeTask)item);
    }

    void InsertDroppedItems(IList<EmployeeTask> employeeTasks, IEnumerable<object> droppedItems, int index) {
        foreach(var item in droppedItems.Reverse())
            employeeTasks.Insert(index, (EmployeeTask)item);
    }

    ObservableCollection<EmployeeTask> GetTaskCollection(object grid) {
        return grid == PlannedTasksTreeList ? PlannedTasks : PendingTasks;
    }

    MarkupString GetEmployeeTaskPriorityIconHtml(EmployeeTask employeeTask) {
        var displayText = TreeListRenderHelper.EmployeeTaskPriorityToString(employeeTask);
        var badgeClass = employeeTask.Priority switch {
            -1 => "bg-success",
            0 => "bg-info",
            1 => "bg-warning",
            _ => throw new ArgumentException()
        };

        string html = string.Format("<span class='badge {0} py-1 px-2' title='{1} priority'>{1}</span>", badgeClass, displayText);
        return new MarkupString(html);
    }
}
See Also