Blazor拖拽功能:如何获取目标对象?
Blazor拖拽功能中获取目标对象的解决方案
问题分析
你当前的代码其实已经通过@ondrop="@((e) => ondropOver(b, blocks.ToList()))"将目标块b传递到了ondropOver方法中,但可能因为以下原因导致无法正确获取或处理目标块:
- 传递
blocks.ToList()创建了列表副本,修改副本不会同步到原数据集合 - 未及时调用
StateHasChanged()触发组件渲染,导致状态更新不生效 - 排序逻辑仅直接赋值Order,未处理其他块的顺序冲突
修正后的前端代码
<div class="pos-top"> <div id="imgGrid" class="grid bg-white" style="grid-template-columns:repeat(@columnCount, @(unitWidth)); grid-auto-flow:dense;"> @foreach (var b in blocks) { @if ((b.Placement[_pageType].Visible == true || showHiddenBlocks == true) && b.Zones != null && b.Zones.Contains(zone)) { var id = b.Id; <div class="col-span-@b.ColSpan row-span-@b.RowSpan relative border border-black box-border @(b.isDragOver?"dropped":"")" style=" order:@b.Placement[_pageType].Order;" @ondblclick="(() => ChangeBlockProperties(b))" draggable="true" data-block-id="@b.Id" id="@id" @ondrop="(() => ondropOver(b))" @ondragover="OnDragOver" @ondragstart="@((e) => ondragstart(e, b))" @ondragenter="@(() => ondragenter(b))" @ondragleave="@(() => ondragleave(b))" @ondragend="@(() => ondragend(b))"> <div class="blockNumberInfo absolute rounded-full bg-red-700 flex justify-center items-center border-2 border-black" style="width:40px;height:20px"> @b.LocalIndex / @b.Placement[_pageType].Order </div> </div> } } </div> </div>
修正后的后端处理代码
// 处理dragover,必须调用PreventDefault才能触发drop事件 public void OnDragOver(DragEventArgs e) { e.PreventDefault(); e.DataTransfer.DropEffect = "move"; } public void ondragstart(DragEventArgs e, FlyerBlock item) { e.DataTransfer.EffectAllowed = "move"; DraggedItem = item; DraggedItemPosition = item.Placement[_pageType].Order; } public void ondragenter(FlyerBlock item) { if (DraggedItem?.Id == item.Id) return; item.isDragOver = true; DragEnter = item; StateHasChanged(); // 触发渲染更新拖拽状态 } public void ondragleave(FlyerBlock item) { item.isDragOver = false; StateHasChanged(); } public async Task ondropOver(FlyerBlock targetItem) { DragEnter = null; if (DraggedItem == null || DraggedItem.Id == targetItem.Id) return; var draggedOrder = DraggedItem.Placement[_pageType].Order; var targetOrder = targetItem.Placement[_pageType].Order; // 调整其他块的顺序,避免Order值重复 if (draggedOrder < targetOrder) { // 拖拽项向后移动,目标及后续块的Order减1 foreach (var block in blocks.Where(b => b.Placement[_pageType].Order > draggedOrder && b.Placement[_pageType].Order <= targetOrder)) { block.Placement[_pageType].Order--; } } else { // 拖拽项向前移动,目标及前面块的Order加1 foreach (var block in blocks.Where(b => b.Placement[_pageType].Order >= targetOrder && b.Placement[_pageType].Order < draggedOrder)) { block.Placement[_pageType].Order++; } } // 设置拖拽项的新顺序 DraggedItem.Placement[_pageType].Order = targetOrder; // 保存更改,直接使用组件的原blocks集合 await BlockplacementEditService.SaveBlockChangesAsync(blocks, DraggedItem, targetOrder, _pageType, zone); DraggedItem = null; targetItem.isDragOver = false; StateHasChanged(); // 更新UI状态 } public void ondragend(FlyerBlock item) { item.isDragOver = false; DraggedItem = null; DragEnter = null; StateHasChanged(); }
关键修改点
- 移除列表副本传递:直接使用组件的
blocks集合,避免修改副本导致数据不同步 - 强制触发状态更新:在修改
isDragOver和Order值后调用StateHasChanged(),确保UI实时更新 - 完善排序逻辑:处理其他块的Order值,避免出现重复排序号
- 规范dragover事件:单独提取方法并调用
PreventDefault(),确保drop事件能正常触发
内容的提问来源于stack exchange,提问作者Adil15
相关产品推荐
相关产品推荐

