You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor中无需JS代码实现同排子容器拖拽交换方法

在Blazor中无需JS实现同排子容器拖拽交换

实现思路

利用Blazor原生HTML拖拽事件(无需自定义JS),通过父组件维护子项列表,在拖拽事件触发时交换子项位置,配合CSS实现拖拽视觉反馈。

步骤1:定义拖拽项模型

创建类存储拖拽项的唯一标识和显示内容:

public class DraggableItem
{
    public Guid Id { get; set; } = Guid.NewGuid();
    public string Content { get; set; } = string.Empty;
}

步骤2:编写父容器组件

父组件负责管理子项列表、处理核心拖拽逻辑:

<div class="drag-container">
    @foreach (var item in Items)
    {
        <DraggableItemComponent 
            Item="item" 
            DraggedItemId="DraggedItemId"
            OnDragStart="() => StartDrag(item.Id)"
            OnDragOver="() => DragOver(item.Id)"
            OnDrop="() => Drop(item.Id)" />
    }
</div>

@code {
    // 初始化示例子项
    private List<DraggableItem> Items { get; set; } = new()
    {
        new DraggableItem { Content = "容器1" },
        new DraggableItem { Content = "容器2" },
        new DraggableItem { Content = "容器3" },
        new DraggableItem { Content = "容器4" }
    };

    // 记录当前拖拽项的ID
    private Guid? DraggedItemId { get; set; }

    // 拖拽开始:标记当前拖拽项
    private void StartDrag(Guid itemId)
    {
        DraggedItemId = itemId;
    }

    // 拖拽经过:交换拖拽项与目标项的位置
    private void DragOver(Guid targetItemId)
    {
        if (DraggedItemId == null || DraggedItemId == targetItemId) return;

        var draggedIndex = Items.FindIndex(i => i.Id == DraggedItemId);
        var targetIndex = Items.FindIndex(i => i.Id == targetItemId);

        if (draggedIndex == -1 || targetIndex == -1) return;

        // 交换列表中两项的位置
        (Items[draggedIndex], Items[targetIndex]) = (Items[targetIndex], Items[draggedIndex]);

        // 更新拖拽项ID,保证连续拖拽时索引正确
        DraggedItemId = targetItemId;
    }

    // 拖拽结束:清空拖拽标记
    private void Drop(Guid targetItemId)
    {
        DraggedItemId = null;
    }
}

步骤3:编写子项组件

子组件负责绑定拖拽事件、接收父组件回调,并提供视觉状态反馈:

<div 
    class="draggable-item @GetItemClass()"
    draggable="true"
    @ondragstart="HandleDragStart"
    @ondragover="HandleDragOver"
    @ondrop="HandleDrop">
    @Item.Content
</div>

@code {
    [Parameter, Required] public DraggableItem Item { get; set; } = null!;
    [Parameter] public Guid? DraggedItemId { get; set; }
    [Parameter] public Action? OnDragStart { get; set; }
    [Parameter] public Action? OnDragOver { get; set; }
    [Parameter] public Action? OnDrop { get; set; }

    // 根据拖拽状态生成样式类
    private string GetItemClass()
    {
        var classList = new List<string>();
        if (DraggedItemId == Item.Id)
        {
            classList.Add("dragging");
        }
        return string.Join(" ", classList);
    }

    private void HandleDragStart(DragEventArgs e)
    {
        e.Data.EffectAllowed = "move";
        OnDragStart?.Invoke();
    }

    private void HandleDragOver(DragEventArgs e)
    {
        e.PreventDefault(); // 必须阻止默认行为才能触发Drop事件
        OnDragOver?.Invoke();
    }

    private void HandleDrop(DragEventArgs e)
    {
        e.PreventDefault();
        OnDrop?.Invoke();
    }
}

步骤4:添加CSS样式

让子项同排显示,并添加拖拽时的视觉效果:

.drag-container {
    display: flex;
    gap: 1rem;
    padding: 1.5rem;
    flex-wrap: wrap;
}

.draggable-item {
    padding: 2rem 1.5rem;
    border: 2px solid #e0e0e0;
    border-radius: 8px;
    cursor: grab;
    background-color: #fff;
    transition: all 0.2s ease;
    min-width: 120px;
    text-align: center;
}

.draggable-item:active {
    cursor: grabbing;
}

.draggable-item.dragging {
    opacity: 0.5;
    transform: scale(0.98);
}

效果说明

  • 拖拽子容器时,该容器会呈现半透明、轻微缩小的视觉反馈
  • 拖拽经过其他子容器时,两者会立即交换位置
  • 整个过程完全基于Blazor的C#逻辑和原生HTML事件,未引入任何JavaScript代码

内容的提问来源于stack exchange,提问作者Cannie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 11:03:20