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

Blazor Server拖拽场景存储变量在函数执行后丢失问题求助

问题原因与解决方案

核心问题

你遇到的变量状态丢失,本质是Blazor Server的组件状态模型与浏览器拖拽事件的特性不匹配:
Blazor Server的组件状态存储在服务器端,dragstart和drop是两个独立的客户端事件,会通过SignalR分别向服务器发起调用。在这两个事件之间,组件可能因重新渲染、上下文切换等原因导致服务器端存储的字段被重置,无法可靠保留拖拽数据。正确的做法是利用浏览器原生的DataTransfer对象在客户端存储拖拽数据,而非依赖服务器端组件字段。


修改后的代码实现

1. 拖拽元素代码(传递事件参数)

<table class="table AssignmentsTable" draggable="true"
       @ondragstart="@(e => AssignmentOnDragStart(e, item.Id, "Location"))"
       @ondragstart:stopPropagation>
    <tr>
        <td>
            <span>@item?.Description</span>
        </td>
    </tr>
</table>

2. 被拖拽元素代码(规范事件处理)

<h5 @ondrop="@(e => AssignmentOnDrop(e, (ParentID ?? 0), "Company"))" 
    @ondragover="@(e => e.PreventDefault())">@company.Name</h5>

3. Razor逻辑代码(使用DataTransfer传递数据)

// 移除原有的服务器端存储字段,改用客户端DataTransfer传递数据

public async Task AssignmentOnDragStart(DragEventArgs e, int id, string type)
{
    await JSRuntime.InvokeVoidAsync("console.log", $"Before: {type}: {id.ToString()}");
    // 将类型和ID存入浏览器DataTransfer,用|分隔便于后续解析
    e.DataTransfer.SetData("text/plain", $"{type}|{id}");
    await JSRuntime.InvokeVoidAsync("console.log", $"Stored in DataTransfer: {type}: {id.ToString()}");
}

public async Task AssignmentOnDrop(DragEventArgs e, int id, string type)
{
    // 必须阻止默认行为,确保drop事件正常触发
    e.PreventDefault();
    
    // 从DataTransfer取出拖拽数据并解析
    var dragData = e.DataTransfer.GetData("text/plain");
    var dataParts = dragData.Split('|');
    if (dataParts.Length != 2)
    {
        await JSRuntime.InvokeVoidAsync("console.log", "Invalid drag data format");
        return;
    }

    string storedAssigneeType = dataParts[0];
    if (!int.TryParse(dataParts[1], out int storedAssigneeID))
    {
        await JSRuntime.InvokeVoidAsync("console.log", "Invalid ID in drag data");
        return;
    }

    await JSRuntime.InvokeVoidAsync("console.log", $"Stored Assignee: {storedAssigneeType}: {storedAssigneeID.ToString()}");
    await JSRuntime.InvokeVoidAsync("console.log", $"{type}: {id.ToString()}");
    
    var result = Service.AddAssignment(storedAssigneeType, storedAssigneeID, type, id);
    await JSRuntime.InvokeVoidAsync("console.log", $"{result.ToString()}");
}

关键注意事项

  • 替换async void为async Task:Blazor中处理异步事件必须用async Task,async void会导致异常无法被捕获,还可能破坏组件状态一致性。
  • 必须调用PreventDefault():在dragover事件中阻止默认行为是触发drop事件的前提,这里改用Blazor的事件参数API更规范。
  • DataTransfer数据格式可扩展:如果需要传递更复杂的数据,可以用JSON格式序列化后存入,解析时再反序列化即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 21:38:41