如何将 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 事件的主要内容,如果未能解决你的问题,请参考以下文章

如何将CString转换成wstring

如何将Ios文件上传到

Qt如何将文字变成图片?

如何将Bitmap保存为本地图片文件?

在MATLAB中如何将图导出

ASP如何将SQLSERVER数据导出到DBF(VF)