Select theme:
Updated on October 2, 2020 to use the latext Blazor syntax (.NET 5)
This blog post shows how to implement drag and drop in server-side Blazor applications. We will use the HTML 5 Drag and Drop API which is built-in in every modern browser.
Hey, we have announced Blazor support in Radzen! Check how you can create a complete Blazor CRUD application in minutes.
Start from the default Blazor project template. Pick BlazorDragAndDrop as the project name.

This is a service which the draggable components will use to communicate with the drop targets.
Add a new file called DragAndDropService.cs in the Data directory:
using System;
namespace BlazorDragAndDrop.Data
{
public class DragAndDropService
{
public object Data { get; set; }
public string Zone { get; set; }
public void StartDrag(object data, string zone)
{
this.Data = data;
this.Zone = zone;
}
public bool Accepts(string zone)
{
return this.Zone == zone;
}
}
}
Then register the DragAndDropService in Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
services.AddSingleton<DragAndDropService>();
}
The next step is to create the component which the users will drag.
Add a new file Draggable.razor in the Shared directory:
@typeparam T
@using BlazorDragAndDrop.Data
@inject DragAndDropService DragAndDropService
<div draggable="true" @ondragstart="@OnDragStart">
@ChildContent
</div>
@code {
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public string Zone { get; set; }
[Parameter]
public T Data { get; set;}
void OnDragStart()
{
// Notify the DragAndDropService what the current Data and Zone are.
DragAndDropService.StartDrag(Data, Zone);
}
}
The Draggable component has three properties.
ChildContent is the user defined draggable content. We simply render it via @ChildContent.Zone is restricts (optinally) where this draggable can be dropped. A draggable can be dropped in a drop target only if their zones have the same value.Data is the user specified data associated with the draggable. Can be anything.The DropTarget accepts Draggable components and triggers an event when the user drops one.
Add a new file DropTarget.cshtml in the Shared directory:
@using BlazorDragAndDrop.Data
@inject DragAndDropService DragAndDropService
@typeparam T
<div ondragover="event.preventDefault()" @ondrop="@OnDrop">
@ChildContent
</div>
@code {
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public string Zone { get; set; }
[Parameter]
public Action<T> Drop { get; set; }
void OnDrop()
{
if (Drop != null && DragAndDropService.Accepts(Zone))
{
Drop((T)DragAndDropService.Data);
}
}
}
The component has three properties.
ChildContent is the user defined drop target content.Zone is specifies (optinally) what draggable components are accepted. A draggable can be dropped in a drop target only if their zones have the same value.Drop is the event handler that the DropTarget will trigger when the user drops an accepted draggable. The Data assocated with the dropped component is provided as argument.Here is how to use the Draggable and DropTarget components in the Index.razor page:
@page "/"
<style>
.draggable {
border: 1px solid #ccc;
border-radius: 5px;
margin: 1rem;
padding: 1rem;
display: inline-block;
cursor: move;
}
.drop-target {
border: 1px dashed #ebebeb;
margin: 1rem;
padding: 1rem;
display: inline-block;
}
</style>
<Draggable Data="@draggableDataA">
<div class="draggable">
Draggable A
</div>
</Draggable>
<Draggable Data="@draggableDataB">
<div class="draggable">
Draggable B
</div>
</Draggable>
<DropTarget T="String" Drop="@OnDrop">
<div class="drop-target">
Accepts Draggable A or B
</div>
</DropTarget>
@if (dropMessage != null) {
@dropMessage
}
<DropTarget T="String" Zone="DropZone">
<div class="drop-target">
Can't drop here
</div>
</DropTarget>
@code {
string draggableDataA = "Draggable Data A";
string draggableDataB = "Draggable Data B";
string dropMessage = null;
void OnDrop(string data)
{
dropMessage = $"Dropped: {data}";
// Important: Invoke StateHasChanged() to update the page
StateHasChanged();
}
}

The complete sample project is available in the Radzen Github repository.
Cheers!
What We Shipped in 2025 (So Far)
October Update: GitHub Copilot, PivotDataGrid, and more new tools to boost your Blazor development
New: RadzenSkeleton Blazor Component
Add AI Chat to Your Blazor Apps with RadzenAIChat
We Rebuilt Our Website with Blazor – Here's Why (and How)
New App Template: Real Estate Website
Radzen Blazor Components v7.0 released!
Radzen is free to use. You can also test the premium features for 15 days.
Start FreeSelect theme: