Search code examples
c#drag-and-dropblazor

Blazor: Drag & Drop list elements


I would like to know how to bind Drag & Drop events to rearrange items in a list.

This is the code I have:

<PageTitle>Drag & Drop</PageTitle>

<ul style="border:1px solid black">
    @foreach (var item in Items)
    {
        <li draggable="true" @* draggable *@
            @[email protected]
            id="@item.Id"              
            @* how to bind drag events? *@
        >@item.Label</li>
    }
</ul>

@code {
    public class Item
    {
        public int Id {get; set;}
        public string Label {get; set; } = default!;
    }
    public List<Item> Items = new() {
        new Item(){Id= 1, Label = "hi 1"},
        new Item(){Id= 2, Label = "hi 2"},
        new Item(){Id= 3, Label = "hi 3"},
        new Item(){Id= 4, Label = "Move me!"},
    };

}

Solution

  • Here I illustrate some basic Drag & Drop html5 event handling operations just with Blazor:

    enter image description here

    Here is the code, self explanatory.

    @page "/"
    
    <PageTitle>Drag & Drop Sample</PageTitle>
    
    <ul style="border:1px solid black">
        @foreach (var item in Items)
        {
            <li draggable="true"
                class="@(DragEnter==item?"inserting":"")"
                @[email protected]
                id="@item.Id"              
                ondragover="event.preventDefault();"
                @ondragstart="@( (e) => hondragstart(e, item))"
                @ondrop="@( () => hondropOverAFriend(item))"
                @ondragenter="@( ()=> hondragenter(item) )"
                @ondragend="@( ()=> hondragend() )"
            >@item.Label</li>
        }
        <div style="height: 1.5em;" 
            ondragover="event.preventDefault();"
            @ondrop="hondropBotton"
            @ondragenter="hondragenterBotton"
        />
    </ul>
    
    <style>
        .inserting
        {
            border-top: 1px solid black;
            margin-top: 5px;
        }
    </style>
    
    @code {
        public class Item
        {
            public int Id {get; set;}
            public string Label {get; set; } = default!;
        }
        public List<Item> Items = new() {
            new Item(){Id= 1, Label = "hi 1"},
            new Item(){Id= 2, Label = "hi 2"},
            new Item(){Id= 3, Label = "hi 3"},
            new Item(){Id= 4, Label = "Move me!"},
        };
        public void  hondropOverAFriend(Item friend)
        {
            DragEnter=null;
            if (DraggedItem == null) return;
            if (DraggedItem == friend) return;
            var friendposition = Items.IndexOf(friend);
            Items.Insert(friendposition, DraggedItem!);
            DraggedItem=null;
        }
        public void  hondropBotton()
        {
            DragEnter=null;
            if (DraggedItem == null) return;
            Items.Add(DraggedItem!);
            DraggedItem=null;
        }
        public void  hondragstart(DragEventArgs e, Item item)
        {
            e.DataTransfer.EffectAllowed = "move"; //does't run
            DraggedItem = item;
            DraggedItemPosition = Items.IndexOf(item);
            Items.Remove(DraggedItem!);
        }    
        public void  hondragenter(Item item)
            =>
            DragEnter = item;    
        public void  hondragenterBotton()
            =>
            DragEnter = null;
        public void  hondragend()
        {
            // never fired IDK why
            if (DraggedItem == null) return;        
            DragEnter = null;
            Items.Insert(DraggedItemPosition, DraggedItem!);        
        }
        private Item? DraggedItem;
        private int DraggedItemPosition;
        private Item? DragEnter;
    }
    

    Disclaimer

    They are some things that I don't know how to do without JSInterop, for example, I was unable to change EffectAllowed or to set data on DataTransfer. People, be free to improve code!