Issue with drag and drop between treeViews once 1 is empty

Hello I am having issue with the TreeView components. I would like to drag and drop between 2  TreeViews but I am unable to do it once one of the tree views are empty. 

Also I was wondering if it is possible to drag and drop 1 value from 1 treeview into another one but to keep that value on both? 

I would like to have an 2 Tree Views where user can select something from the left side and drag to right but I would like too keep the left tree view as it was initialized.  
Image_7028_1748334440805


  @page "/test"
<div class="page-content">
    <div class="row">
        <div class="pb-2 pt-2">
            <div class="col-lg-12 control-section custom-tree">
                <div class="control-wrapper">
                    <div class="col-lg-4 tree-data">
                        <h4>Front End Teams</h4>
                        <div class="content">
                            <div class="tree-list">


                                <SfTreeView ID="tree2" TValue="TeamDetails" AllowDragAndDrop="true">
                                    <TreeViewFieldsSettings TValue="TeamDetails" Id="Id" Text="Name" Child="Children" DataSource="@JSTeam" Expanded="Expanded"></TreeViewFieldsSettings>
                                    <TreeViewEvents TValue="TeamDetails"></TreeViewEvents>
                                </SfTreeView>
                            </div>
                        </div>
                    </div>
                    <div class="col-lg-4 tree-data">
                        <h4>Back End Teams</h4>
                        <div class="content">
                            <div class="tree-list">


                                <SfTreeView ID="tree1" TValue="TeamDetails" AllowDragAndDrop="true">
                                    <TreeViewFieldsSettings TValue="TeamDetails" Id="Id" Text="Name" Child="Children" DataSource="@ASPTeam" Expanded="Expanded"></TreeViewFieldsSettings>
                                    <TreeViewEvents TValue="TeamDetails"></TreeViewEvents>
                                </SfTreeView>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
@code {
    public class TeamDetails
    {
        public string? Id { get; set; }
        public string? Name { get; set; }
        public string? Text { get; set; }
        public bool Expanded { get; set; }
        public bool Selected { get; set; }
        public List<TeamDetails> Children;
    }
    // Specifies the DataSource value for Front End Teams TreeView component.
    List<TeamDetails> ASPTeam = new List<TeamDetails>();
    // Specifies the DataSource value for Back End Teams TreeView component.
    List<TeamDetails> JSTeam = new List<TeamDetails>();
    protected override void OnInitialized()
    {
        base.OnInitialized();
        List<TeamDetails> ASP_EmployeeDetails1 = new List<TeamDetails>();
        List<TeamDetails> ASP_EmployeeDetails2 = new List<TeamDetails>();
        List<TeamDetails> JS_EmployeeDetails1 = new List<TeamDetails>();
        List<TeamDetails> JS_EmployeeDetails2 = new List<TeamDetails>();
        ASPTeam.Add(new TeamDetails
            {
                Id = "01",
                Name = "ASP.NET MVC Team",
                Expanded = true,
                Children = ASP_EmployeeDetails1,
            });
        ASP_EmployeeDetails1.Add(new TeamDetails
            {
                Id = "01-01",
                Name = "Smith"
            });
        ASP_EmployeeDetails1.Add(new TeamDetails
            {
                Id = "01-02",
                Name = "Johnson"
            });
        ASP_EmployeeDetails1.Add(new TeamDetails
            {
                Id = "01-03",
                Name = "Anderson"
            });


    }
}


<style>
    /* Sample specific styles */
    .custom-tree {
        overflow: auto;
    }


        .custom-tree .control-wrapper {
            position: relative;
            min-width: 700px;
            min-height: 400px;
            overflow: auto;
        }


    #list {
        min-height: 288px;
        border: 0;
    }


    .tree1-data, .tree2-data, .tree3-data {
        padding: 15px;
        margin-bottom: 25px;
    }


    #tree1, #tree2, #list {
        height: 300px;
        overflow: auto;
    }


    .tree-list {
        margin: 0 auto;
        border: 1px solid #dddddd;
        border-radius: 3px;
        min-height: 288px;
    }


    .custom-delete::before {
        content: "\e700";
        cursor: pointer;
        color: rgba(0, 0, 0, 0.54);
        font-size: 15px;
        vertical-align: sub;
        float: right;
    }


    .custom-delete {
        float: right;
        font-family: 'cross-circle';
    }


    @@media (max-width: 1200px) {
        .tree-data {
            width: 33.33333333%;
            float: left;
        }
    }


    @@font-face {
        font-family: 'cross-circle';
        src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAAKAIAAAwAgT1MvMj0gSRsAAAEoAAAAVmNtYXDnEOdVAAABiAAAADZnbHlmKuKzFgAAAcgAAABkaGVhZBRzllcAAADQAAAANmhoZWEHmQNrAAAArAAAACRobXR4B+gAAAAAAYAAAAAIbG9jYQAyAAAAAAHAAAAABm1heHABDgAkAAABCAAAACBuYW1lyFBwKAAAAiwAAAJhcG9zdJx8QW4AAASQAAAAOwABAAADUv9qAFoEAAAA//4D6gABAAAAAAAAAAAAAAAAAAAAAgABAAAAAQAA8246G18PPPUACwPoAAAAANi1qMQAAAAA2LWoxAAAAAAD6gPqAAAACAACAAAAAAAAAAEAAAACABgAAgAAAAAAAgAAAAoACgAAAP8AAAAAAAAAAQP0AZAABQAAAnoCvAAAAIwCegK8AAAB4AAxAQIAAAIABQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUGZFZABA5wDnAANS/2oAWgPqAJYAAAABAAAAAAAABAAAAAPoAAAAAAACAAAAAwAAABQAAwABAAAAFAAEACIAAAAEAAQAAQAA5wD//wAA5wD//wAAAAEABAAAAAEAAAAAAAAAMgAAAAIAAAAAA+oD6gALABcAAAEHFwcnByc3JzcXNwUWABc2ADcmACcGAALkg4NqhINqg4Nqg4T9iAYBG9PUARsFBf7l1NP+5QJ6hIZqg4Nqg4RqgIPu0/7lBgYBG9PUARsFBf7lAAAAABIA3gABAAAAAAAAAAEAAAABAAAAAAABAAwAAQABAAAAAAACAAcADQABAAAAAAADAAwAFAABAAAAAAAEAAwAIAABAAAAAAAFAAsALAABAAAAAAAGAAwANwABAAAAAAAKACwAQwABAAAAAAALABIAbwADAAEECQAAAAIAgQADAAEECQABABgAgwADAAEECQACAA4AmwADAAEECQADABgAqQADAAEECQAEABgAwQADAAEECQAFABYA2QADAAEECQAGABgA7wADAAEECQAKAFgBBwADAAEECQALACQBXyBjcm9zcy1jaXJjbGVSZWd1bGFyY3Jvc3MtY2lyY2xlY3Jvc3MtY2lyY2xlVmVyc2lvbiAxLjBjcm9zcy1jaXJjbGVGb250IGdlbmVyYXRlZCB1c2luZyBTeW5jZnVzaW9uIE1ldHJvIFN0dWRpb3d3dy5zeW5jZnVzaW9uLmNvbQAgAGMAcgBvAHMAcwAtAGMAaQByAGMAbABlAFIAZQBnAHUAbABhAHIAYwByAG8AcwBzAC0AYwBpAHIAYwBsAGUAYwByAG8AcwBzAC0AYwBpAHIAYwBsAGUAVgBlAHIAcwBpAG8AbgAgADEALgAwAGMAcgBvAHMAcwAtAGMAaQByAGMAbABlAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAHUAcwBpAG4AZwAgAFMAeQBuAGMAZgB1AHMAaQBvAG4AIABNAGUAdAByAG8AIABTAHQAdQBkAGkAbwB3AHcAdwAuAHMAeQBuAGMAZgB1AHMAaQBvAG4ALgBjAG8AbQAAAAACAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAgEDABFjaXJjbGUtY2xvc2UtLS0wMgAAAA==) format('truetype');
        font-weight: normal;
        font-style: normal;
    }


    .col-lg-4.tree-data {
        float: left;
    }
</style>

1 Reply 1 reply marked as answer

SJ Saravanan Jayavel Syncfusion Team May 29, 2025 05:27 PM UTC

Hi Pawel Szpytma,


Thank you for your query.


To achieve your requirement of dragging a node from one TreeView to another while retaining the node in the original TreeView, we have prepared a working sample for your reference.


Refer the code snippet below:


[Home.razor]


 

<SfTreeView TValue="TeamDetails" AllowDragAndDrop="true" @ref="LeftTree">

<TreeViewFieldsSettings TValue="TeamDetails" DataSource="@LeftTreeData" Id="Id" Text="Name" Child="Children"></TreeViewFieldsSettings>

<TreeViewEvents TValue="TeamDetails" OnNodeDragStop="OnDragStopLeft"></TreeViewEvents>

</SfTreeView>

 

<SfTreeView TValue="TeamDetails" AllowDragAndDrop="true" @ref="RightTree">

<TreeViewFieldsSettings TValue="TeamDetails" DataSource="@RightTreeData" Id="Id" Text="Name" Child="Children"></TreeViewFieldsSettings>

<TreeViewEvents TValue="TeamDetails" OnNodeDragStop="OnDragStopLeft"></TreeViewEvents>

</SfTreeView>

 

 

 

@code {

 

private SfTreeView<TeamDetails> LeftTree;

private SfTreeView<TeamDetails> RightTree;

 

private void OnDragStopLeft(DragAndDropEventArgs args)

{

args.Cancel = true; // Prevent default move

var draggedNode = args.DraggedNodeData;

var copyNode = new TeamDetails

{

Id = Guid.NewGuid().ToString(), // Unique ID to avoid conflicts

Name = draggedNode.Text

};

// Add to dropped position (child of dropped node if applicable)

RightTree.AddNodes(new List<TeamDetails> { copyNode }, args.DroppedNodeData?.Id);

StateHasChanged(); 

}

}

 


In this sample Drag-and-drop is enabled for both TreeViews. When a node is dragged from the left TreeView and dropped into the right, the original node remains unchanged in the left TreeView. A copy of the dragged node is added to the right TreeView using the AddNodes method.


We achieve this behavior by canceling the default drag operation and programmatically adding a new node object to the target TreeView's data source.


For your reference we attached sample.


Sample: Attached as a zip file


Please let us know if you need that enhancement or have any other questions.


Regards,

Saravanan J


Attachment: TreeviewSample_7ee9fb47.zip

Marked as answer
Loader.
Up arrow icon