Blazor拖放如何获取目标对象?

huangapple go评论61阅读模式
英文:

Blazor drag and drop how to get target object?

问题

以下是您要翻译的内容:

"I can't seem to figure out the right way to get the target object. Here is the code front end code that is supposed to have drag and drop functionality:

<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="((e) => ondropOver(b, blocks.ToList()))"
				ondragover="event.preventDefault();"
				ondragstart="((e) => ondragstart(e, b, blocks.ToList()))"
				ondragenter="(() => ondragenter(b))"
				ondragleave="(() => { b.isDragOver = false; })"
				ondragend="(() => ondragend(b, blocks.ToList()))">
					<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>

This is my code that is moving the blocks around:

public async void ondropOver(FlyerBlock item, List<FlyerBlock> flyerBlocks)
{
    DragEnter = null;
    if (DraggedItem == null) return;
    if (DraggedItem == item) return;
    DraggedItem.Placement[_pageType].Order = item.Placement[_pageType].Order;
    await BlockplacementEditService.SaveBlockChangesAsync(flyerBlocks, DraggedItem, DraggedItem.Placement[_pageType].Order, _pageType, zone);
    DraggedItem = null;
    item.isDragOver = false;
    //StateHasChanged();
}

public void ondragstart(DragEventArgs e, FlyerBlock item, List<FlyerBlock> flyerBlocks)
{
    e.DataTransfer.EffectAllowed = "move";
    DraggedItem = item;
    DraggedItemPosition = item.Placement[_pageType].Order;
}

public void ondragenter(FlyerBlock item)
{
    item.isDragOver = true;
    DragEnter = item;
}

public async void ondragend(FlyerBlock item, List<FlyerBlock> flyerBlocks)
{
    item.isDragOver = false;
    if (DraggedItem == null) return;
    DragEnter = null;
    // item.isDragOver = true;
}

The issue I am running into is that I dont know how to pass the targetblock into my drop over event. I tried using DragEventArgs but that does not work I have also tried using jsruntime but I can only extract the dragged block. I want to be able to get the target block so I can update the order correctly. Any help would be appreciated!"

英文:

I can't seem to figure out the right way to get the target object. Here is the code front end code that is supposed to have drag and drop functionality:

	&lt;div class=&quot;pos-top&quot;&gt;
		&lt;div id=&quot;imgGrid&quot; class=&quot;grid bg-white&quot; style=&quot;grid-template-columns:repeat(@columnCount, @(unitWidth)); grid-auto-flow:dense;&quot;&gt;
			@foreach (var b in blocks)
			{
				@if ((b.Placement[_pageType].Visible == true || showHiddenBlocks == true) &amp;&amp; b.Zones != null &amp;&amp; b.Zones.Contains(zone))
				{
					var id = b.Id;
					&lt;div class=&quot;col-span-@b.ColSpan row-span-@b.RowSpan relative border border-black box-border @(b.isDragOver?&quot;dropped&quot;:&quot;&quot;)&quot; style=&quot; order:@b.Placement[_pageType].Order;&quot; @ondblclick=&quot;(() =&gt; ChangeBlockProperties(b))&quot;
			 draggable=&quot;true&quot;
			 data-block-id=&quot;@b.Id&quot;
			 id=&quot;@id&quot; @ondrop=&quot;@((e) =&gt; ondropOver(b, blocks.ToList()))&quot;
			 ondragover=&quot;event.preventDefault();&quot;
			 @ondragstart=&quot;@((e) =&gt; ondragstart(e, b, blocks.ToList()))&quot;
			 @ondragenter=&quot;@(() =&gt; ondragenter(b))&quot;
			 @ondragleave=&quot;@(() =&gt; { b.isDragOver = false; })&quot;
			 @ondragend=&quot;@(() =&gt; ondragend(b, blocks.ToList()))&quot;&gt;
						&lt;div class=&quot;blockNumberInfo absolute rounded-full bg-red-700 flex justify-center items-center border-2 border-black&quot;
				 style=&quot;width:40px;height:20px&quot;&gt;
							@b.LocalIndex / @b.Placement[_pageType].Order
						&lt;/div&gt;


								&lt;/div&gt;
							}
						}
					&lt;/div&gt;
				}
			}
		&lt;/div&gt;

This is my code that is moving the blocks around:

public async void ondropOver(FlyerBlock item, List&lt;FlyerBlock&gt; flyerBlocks)
	{
		DragEnter = null;
		if (DraggedItem == null) return;
		if (DraggedItem == item) return;
		DraggedItem.Placement[_pageType].Order = item.Placement[_pageType].Order;
		await BlockplacementEditService.SaveBlockChangesAsync(flyerBlocks, DraggedItem, DraggedItem.Placement[_pageType].Order, _pageType, zone);
		DraggedItem = null;
		item.isDragOver = false;
		//StateHasChanged();
	}

	public void ondragstart(DragEventArgs e, FlyerBlock item, List&lt;FlyerBlock&gt; flyerBlocks)
	{
		e.DataTransfer.EffectAllowed = &quot;move&quot;;
		DraggedItem = item;
		DraggedItemPosition = item.Placement[_pageType].Order;
	}

	public void ondragenter(FlyerBlock item)
	{
		item.isDragOver = true;
		DragEnter = item;
	}

	public async void ondragend(FlyerBlock item, List&lt;FlyerBlock&gt; flyerBlocks)
	{
		item.isDragOver = false;
		if (DraggedItem == null) return;
		DragEnter = null;
		// item.isDragOver = true;

	}

The issue I am running into is that I dont know how to pass the targetblock into my drop over event. I tried using DragEventArgs but that does not work I have also tried using jsruntime but I can only extract the dragged block. I want to be able to get the target block so I can update the order correctly. Any help would be appreciated!

答案1

得分: 1

这是我修改后的拖放服务。我在DragAndDropService.cs类中添加了Target属性,用于在放置时保存目标对象。

原始源代码可以在此处找到:https://www.radzen.com/blog/blazor-drag-and-drop/

using System;

namespace MyToolSource.Data
{
    public class DragAndDropService
    {
        public object Data { get; set; }
        public object Target { get; set; }
        public string Zone { get; set; }

        public void StartDrag(object data, object target, string zone)
        {
            this.Data = data;
            this.Target = target;
            this.Zone = zone;
        }

        public bool Accepts(string zone)
        {
            return this.Zone == zone;
        }
    }
}

这是Draggable.cs类。我添加了Target属性来保存目标对象。尽管此时你还没有目标对象,但必须具有在后续HTML中使用DropTarget时将被填充的属性。

@typeparam T
@using MyToolSource.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 Target { get; set; }

    [Parameter]
    public T Data { get; set; }

    void OnDragStart()
    {
        // 通知DragAndDropService当前的Data和Zone是什么。
        DragAndDropService.StartDrag(Data, Target, Zone);
    }
}

这是DropTarget.cs类。我添加了Target属性,以在源被放置后保存目标对象。

@using MyToolSource.Data
@inject DragAndDropService DragAndDropService
@typeparam T

<div ondragover="event.preventDefault()" @ondrop="@OnDrop">
    @ChildContent
</div>

@code {
    [Parameter]
    public RenderFragment? ChildContent { get to set; }

    [Parameter]
    public string Zone { get; set; }

    [Parameter]
    public T Target { get; set; }

    [Parameter]
    public Action<T, T>? Drop { get; set; }

    void OnDrop()
    {
        if (Drop != null && DragAndDropService.Accepts(Zone))
        {
            Drop((T)DragAndDropService.Data, Target);
        }
    }
}

在HTML中,将Target属性添加到DropTarget包装器中。

<Draggable Data="@customer">
    <td class="draggable customer-x">
        @customer.FirstName
    </td>
</Draggable>

<DropTarget T="vCustomer" Drop="@OnDrop" Target="@customer">
    <td id="@customer.CustomerId"></td>
</DropTarget>

OnDrop方法。现在你有了目标对象,可以使用它了。

string dropMessage = null;

void OnDrop(vCustomer data, object target)
{
    dropMessage = $"Dropped: {data.FirstName} on {((vCustomer)target).FirstName}";

    // 重要:调用StateHasChanged()以更新页面
    StateHasChanged();
}

希望这有所帮助!

英文:

This is my modified drag and drop service. I added the Target property to the DragAndDropService.cs class to hold the target object when dropping.

The original source code can be found here: https://www.radzen.com/blog/blazor-drag-and-drop/

using System;

namespace MyToolSource.Data
{
    public class DragAndDropService
    {
        public object Data { get; set; }
        public object Target { get; set; }
        public string Zone { get; set; }

        public void StartDrag(object data, object target, string zone)
        {
            this.Data = data;
            this.Target = target;
            this.Zone = zone;
        }

        public bool Accepts(string zone)
        {
            return this.Zone == zone;
        }
    }
}

This is the Draggable.cs class.
I added the Target property to hold the target object. Although you don't have the target object at this point it must have the property that will be populated when you use the DropTarget later in the html.

@typeparam T
@using MyToolSource.Data
@inject DragAndDropService DragAndDropService

&lt;div draggable=&quot;true&quot; @ondragstart=&quot;@OnDragStart&quot;&gt;
    @ChildContent
&lt;/div&gt;

@code {
    [Parameter]
    public RenderFragment ChildContent { get; set; }

    [Parameter]
    public string Zone { get; set; }

    [Parameter]
    public T Target { get; set; }

    [Parameter]
    public T Data { get; set; }

    void OnDragStart()
    {
        // Notify the DragAndDropService what the current Data and Zone are.
        DragAndDropService.StartDrag(Data, Target, Zone);
    }
}

This is the DropTrget.cs class. I added the Target property to hold the target object once the source is dropped.

@using MyToolSource.Data
@inject DragAndDropService DragAndDropService
@typeparam T

&lt;div ondragover=&quot;event.preventDefault()&quot; @ondrop=&quot;@OnDrop&quot;&gt;
    @ChildContent
&lt;/div&gt;

@code {
    [Parameter]
    public RenderFragment? ChildContent { get; set; }

    [Parameter]
    public string Zone { get; set; }

    [Parameter]
    public T Target { get; set; }

    [Parameter]
    public Action&lt;T,T&gt;? Drop { get; set; }

    void OnDrop()
    {
        if (Drop != null &amp;&amp; DragAndDropService.Accepts(Zone))
        {
            Drop((T)DragAndDropService.Data, Target) ;
        }
    }
}

In the HTML add the Target=@customer to the DropTarget wrapper.

&lt;Draggable Data=&quot;@customer&quot; &gt;
    &lt;td class=&quot;draggable customer-x&quot;&gt;
       @customer.FirstName
    &lt;/td&gt;
&lt;/Draggable&gt; 

       
&lt;DropTarget T=&quot;vCustomer&quot; Drop=&quot;@OnDrop&quot; Target=@customer &gt;
    &lt;td id=&quot;@customer.CustomerId&quot; &gt;&lt;/td&gt;
&lt;/DropTarget&gt;

The OnDrop method. Now that you have the target object you can use it.

string dropMessage = null;

void OnDrop(vCustomer data, object target)
{
    dropMessage = $&quot;Dropped: {data.FirstName} on {((vCustomer)target).FirstName}&quot;;

    // Important: Invoke StateHasChanged() to update the page
    StateHasChanged();
}

Hope this helps!

huangapple
  • 本文由 发表于 2023年2月18日 00:14:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75486729.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定