通过调用 C# 代码的 JS 更新 Blazor

Ber*_*ian 1 javascript interop blazor

我正在尝试Blazor在由js. Js使用互操作在事件上调用 C# 代码,我需要以某种方式调用this.StateHasChangedc# 回调:

JS

window.methods = {
    timeout: null,
    setTimeout: function () {
        timeout = window.setInterval(async function () {
            console.log("From js timeout occured ,sending to .net");
            await DotNet.invokeMethodAsync('[assembly name]', "TimeoutCallback", Date.now().toString());
        }, 2000);
    },

    clearTimeout: function () {
        if (this.timeout == null || this.timeout == undefined) {
            return;
        }
        console.log("Clearing timeout");
        window.clearTimeout(timeout);
    }
}
Run Code Online (Sandbox Code Playgroud)

C#

@inherits StuffBase
@page "/test"

Current value: @val
<button onclick="@(async()=>await StartTimeout())">Start timeout </button>
<button onclick="@(async()=>await ClearTimeout())">Clear timeout</button>

public class StuffBase : BlazorComponent {

        protected static string val { get; set; }
        protected async Task StartTimeout() {
            await JSMethods.SetTimeout();
        }
        [JSInvokable("TimeoutCallback")]  //gets called by js on event !
        public static async Task TimeoutCallback(string data) {

            val = data; 
            Console.WriteLine("From callback ,received:" + data); //gets updated
            await Task.Delay(1000);
           //how can i call this.StateHasChanged
        }
        protected async Task ClearInterval() {
            await JSMethods.ClearInterval();
        }
    }
Run Code Online (Sandbox Code Playgroud)

互操作

public class JSMethods {
        public static async Task SetTimeout() {
            await JSRuntime.Current.InvokeAsync<string>("methods.setTimeout");
        }
        public static async Task ClearTimeout() {
            await JSRuntime.Current.InvokeAsync<string>("methods.clearTimeout");
        }   
    }
Run Code Online (Sandbox Code Playgroud)

正如您首先看到的那样,我从c#->调用setTimeout,在 js 中将超时与其处理程序附加在一起。发生的事情是,我设法TimeoutCallbackjs但是得到了调用,而在console我更新我的值时,我需要以某种方式通知UI它自己进行更新。

我怎样才能实现这一点,因为我.NET调用的所有方法js 都有(根据文档)static

Chr*_*nty 9

我认为将 C# 实例传递给 JS 并让您的 JS 调用回该 C# 实例是一个更好的选择。

资料库

    public class StuffBase : ComponentBase
    {
        protected static string val { get; set; }

        protected async Task StartTimeout()
        {
            await JSRuntime.Current.InvokeAsync<string>("methods.setTimeout", new DotNetObjectRef(this));
        }

        [JSInvokable("TimeoutCallback")]  //gets called by js on event !
        public async Task TimeoutCallback(string data)
        {
            val = data;
            Console.WriteLine("From callback ,received:" + data); //gets updated
            await Task.Delay(1000);
            StateHasChanged();
        }
        protected async Task ClearTimeout()
        {
            await JSMethods.ClearTimeout();
        }
    }
Run Code Online (Sandbox Code Playgroud)

JS

window.methods = {
    timeout: null,
    setTimeout: function (stuffBaseInstance) {
        timeout = window.setInterval(async function () {
            console.log("From js timeout occured ,sending to .net");
            await stuffBaseInstance.invokeMethodAsync('TimeoutCallback', Date.now().toString());
        }, 2000);
    },

    clearTimeout: function () {
        if (this.timeout == null || this.timeout == undefined) {
            return;
        }
        console.log("Clearing timeout");
        window.clearTimeout(timeout);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 有用 !只是一个小更新:在 .Net Core 3.1 中,“DotNetObjectRef”类已更改为“DotNetObjectReference”。这意味着必须将“new DotNetObjectRef(this)”更改为“DotNetObjectReference.Create(this)”才能使代码正常工作。 (2认同)