asp.net core blazorでJavascriptからC#メソッドを呼び出す方法をMSのサイトや、他のサイトで検索した結果、staticメソッドや他クラスインスタンスメソッドを呼び出す方法については書いてあったが、ページクラスのメソッド呼出しについて書いてあるサイトが見つからなかった。
ページクラスのメソッドが呼べれば、クラス変数がそのまま使用できるので、変数とバインドされているHTMLエレメント値を直接いじれるので便利だと思い、色々試してみた。
サイトに書かれていた説明では、呼出されるC#メソッドには[JSInvokable]属性をつける必要がある。これはどのサイトでも同じことが書かれている。
staticメソッドの場合は、 下記のような感じでJavascriptから呼び出すことが可能。
Dotnet.invokeMethod(<アプリ名>,<メソッド名>[,パラメータ1[,パラメータ2...]])
または
Dotnet.invokeMethodAsync(上記と同様)
ただし、staticメソッドなので、バインドされたページインスタンス変数にはアクセスできない。
もう一つ例が載っているのが、ヘルパークラスを介した呼出し。
C#側
var helper = new MyJsHelper();
await JSRuntime.InvokeVoidAsync("JsFunc",
DotNetObjectReference.Create(helper));
JS側
function JsFunc(helper) {
helper.invokeMethodAsync(・・・); // invokeMethodも使用可
}
でも、同じようにバインドされたページインスタンス変数にはアクセスできないよね。(もちろん、ページインスタンスをヘルパーインスタンス内に保存すれば大丈夫かもしれないけれど・・・)
で、上記を見てもしかしてと思って以下のようなコードを書いてみた。
C#側
private string Mesg = "";
・・・
[JSInvokable]
public void CSMethod(int p1, double p2, string p3) {
Mesg = $"p1={p1}, p2={p2}, p3={p3}";
this.StateHasChanged(); // JSから呼び出された場合は自動更新されないので
}
・・・
await JSRuntime.InvokeVoidAsync("JsFunc",
DotNetObjectReference.Create(this),
"CSMethod",10,3.14,"Hello");
JS側
function JsFunc(helper,func,p1,p2,p3) {
helper.invokeMethodAsync(func,p1,p2,p3);
}
見事に動いてくれました。
で、これ使って何をやりたかったかというと、BingMap等のイベントハンドラをC#で書きたかっただけなのです。実際には、ピン等を追加したりするためにJS関数を細切れに作って、C#から呼び出すことになるんだけどね・・・
ちなみに、以下のようなJavascript関数を作って、MapのEvent Handlerを指定している。他のコントロールなどにも流用ができそう。
// event:イベント文字列(ex:”click”)
// helper:C#側でDotNetObjectReference.Create(this)をセット
// funname:C#のメソッド名
function AttachEvents(event, helper, funname) {
Microsoft.Maps.Events.addHandler(MapInstance, event,
function(e) {
helper.invokeMethodAsync(funname,e.location) ;
}
);
}