如何将 DotNetObjectReference 传递给 JS DOM 事件
Posted
技术标签:
【中文标题】如何将 DotNetObjectReference 传递给 JS DOM 事件【英文标题】:How to pass DotNetObjectReference to JS DOM-event 【发布时间】:2022-01-12 10:50:45 【问题描述】:我正在尝试在 Blazor 中使用 JS 拖放,这通常可以正常工作,但我想在 ondragstart
事件期间设置自定义拖动图像。一般来说,我的代码如下所示:
<div class="some-draggable-container"
draggable="true"
ondragstart="Element.dragStartHandler(event, '@(ImageSrcBase64)')" >
</div>
Element.dragStartHandler = function(event, imgSrcBase64)
var img = new Image();
img.src = imgSrcBase64;
event.dataTransfer.setDragImage(img, 0, 0);
我遇到的问题是我需要在设置拖动图像后调用 .Net 函数,但我找不到将所需的DotNetObjectReference
传递给 JS 部分的方法。
简单地将新创建的 objectRef 传递给 JS 事件调用会导致 Unexpected end of input
错误。
ondragstart="Element.dragStartHandler(event, '@(ImageSrcBase64)', @(DotNetObjectReference.Create(this)))"
同样使用JsonSerializer
并不能解决问题。它确实会序列化对象并且 JS 能够反序列化它,但正如预期的那样,DotNet.invokeMethod()
方法不存在。
ondragstart="Element.dragStartHandler(event, '@(ImageSrcBase64)', @(JsonSerializer.Serialize(DotNetObjectReference.Create(this))))"
使用 Blazor 事件并在 .Net 中完全处理它不提供设置拖动图像的能力,因为传递的 DragEventArgs
不完全符合 JS 的。
通过IJSRuntime
将事件参数传递给JS函数会导致错误,因为它与原生JS事件不同,所以至少缺少setDragImage()
方法。
有什么办法可以使这个工作吗?我不想玩弄 JS-to-static-.Net 调用和 guid 或那种解决方法。
编辑
正如@MisterMagoo 在现已删除的评论中提到的那样:在OnAfterRender
的第一个周期中将DotNetObjectReference
传递给JS 部分以及静态guid 并在需要时稍后引用它是一种足够的方式。
问题在于,在我的情况下,列表很容易达到约 50-100 个条目长,我不知道这会如何影响内存的性能。所以在小情况下这会很好,但在我的情况下可能不是。
编辑 所以首先要澄清我选择解决这个问题的方式的原因:我知道我可以通过简单地创建一个跟随光标的图像来纯粹在 Blazor 中解决这个问题。但是通过 JS 已经存在一种设置拖动图像的方法,该方法由浏览器本身在图像定位和移动方面进行处理。所以我想走性能效率最高的路线,而不是充分利用 Blazor,因为我们的应用程序的性能窗口很窄。
【问题讨论】:
这是一种非常复杂的方法来解决天生就不好的情况,因为这不是做事的方法。我建议您继续学习并掌握 Blazor 的编程模式,在 ajax 中添加您自己的方法,以便通过 JSON 在 C# 中工作更深层次 @LeandroBardelli 如果你对这个问题很熟悉,或者可以给出可行的建议,我想这应该也是一个很好的答案。 @IvanYang 我不想冒犯,实际上我的评论与问题无关,我只是认为(对我来说,以我的卑微经验)这会更容易和更快以尝试解决此问题的良好模式进行重构 当我遇到这种情况时,请务必尝试查看是否擦除并重新开始可以解决我最初选择的路径 抱歉,我的英语有时听起来很难听。绝对是我试图建议,而不是冒犯 【参考方案1】:这只是我从内存中写在记事本中的错误伪代码,并且代码确实指向循环,但它应该让您了解如何调用 javascript,然后将数据发送回 c#
在 js 文件中:
window.myBlazor =
doSomething: function(cSharpObjectReference, val1, val2)
// some js stuff happens
cSharpObjectReference.Notify(someData);
在cs文件中:
public static class MyInterops
private static readonly string _BaseObjectContainer = "myBlazor";
public static async Task DoSomethingCs(IJSRuntime jsRuntime, ObjectJavaScriptShouldUse cSharp, MyModel model)
await jsRuntime.InvokeVoidAsync($"_BaseObjectContainer.doSomething", DotNetObjectReference.Create(cSharp), model.Val1, model.Val2);
public class ObjectJavaScriptShouldUse
private readonly IJSRuntime _jsRuntime;
[JSInvokable]
public async ValueTask Notify(MouseEvent eventArgs)
await MyInterops.DoSomethingCs(_jsRuntime, this, eventArgs); //i accidentally pointed these calls in recursion, but you get the idea
【讨论】:
我知道你要去哪里,但你的答案通常是针对 JS 互操作而不是我的具体情况。再说一遍:问题是我无法将ondragstart
事件的 JS 事件参数传递给 JS(我需要立即传递它,因为在其他所有方式上功能都会丢失),同时还传递了一个 DotNetObjectReference调用(那是因为有很多对象引用同一个函数)。
我只会让 html/js 处理 ui 中的拖动并挂钩到 onDragEnd 事件并将最终位置发送到您的代码。除了在 js 和 cs 之间来回传递数据之外,您的原始帖子并没有完全清楚您要实现的目标。你必须按照我建议的方式去做,但是如果你尝试从 js 传递整个对象,你会得到序列化错误,所以只传递重要的数据并在 js 或 cs 中重建以上是关于如何将 DotNetObjectReference 传递给 JS DOM 事件的主要内容,如果未能解决你的问题,请参考以下文章