1.WebView2の初期化を行う。
1.NuGetでMicrosoft.Web.WebView2をインストールします。
2.Visual StudioのツールボックスのWebView2をGUIデザイナでFormに配置します。
3.FormのOnLoad内でEnsureCoreWebView2Asyncを実行しWebView2を初期化します。
※awaitで確実に完了を待ちます。
namespace TestApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override async void OnLoad(EventArgs e)
{
var environment = await CoreWebView2Environment.CreateAsync(null, System.IO.Directory.GetCurrentDirectory());
await this.WebView2.EnsureCoreWebView2Async(environment);
base.OnLoad(e);
}
}
}
2.WebView2に表示するWebページを作る。
次に、WebView2で表示するhtmlファイルを作ります。
index.htmlというファイル名にしてDドライブ直下に保存しました。
JavaScriptは後で追加します。
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
テスト
</body>
</html>
3.WebView2でWebページを表示する。
WebView2でindex.htmlを表示する処理を追加します。
CoreWebView2InitializationCompletedイベントでWebView2コントロールの初期化の完了を捕捉してから表示(Navigateを実行)する必要があります。
using Microsoft.Web.WebView2.Core;
using System;
using System.Windows.Forms;
namespace TestApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.WebView2.CoreWebView2InitializationCompleted += WebView2_CoreWebView2InitializationCompleted;
}
protected override async void OnLoad(EventArgs e)
{
var environment = await CoreWebView2Environment.CreateAsync(null, System.IO.Directory.GetCurrentDirectory());
await this.WebView2.EnsureCoreWebView2Async(environment);
base.OnLoad(e);
}
private void WebView2_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
{
if (e.IsSuccess)
{
this.WebView2.CoreWebView2.Navigate(@"D:\index.html");
}
}
}
}
4.コントローラークラスを作る。
WebView2とのデータ送受信を行うコントローラークラスを作ります。
MVCモデルのコントローラーに該当すると思われる為、クラス名はControllerにしました。
Controllerは、WebView2への参照を保持し、その参照を通じて送受信を行います。
クラスに[ComVisible(true)]属性を付け、publicにする必要があります。
namespace TestApp1
{
[ComVisible(true)]
public class Controller
{
private WebView2 View { get; set; }
public Controller(WebView2 view)
{
View = view;
}
}
}
5. C#からJavaScriptへのデータ送信
C#からJavaScriptへデータを送信出来るようにします。
コントローラーに3つのメソッドを作ります。
| メソッド名 | 機能 | JSでの受け取り方 | |
|---|---|---|---|
| 1 | PostWebMessageAsString | 文字列送信 | messageイベント |
| 2 | PostWebMessageAsJson | JSON文字列送信 | messageイベント 必要に応じてJSON.parseする |
| 3 | ExecuteScriptAsync | JSの関数を実行 | 呼び出されるので受け取り手順なし JSからC#への戻り値は常にJSON ※参照 |
namespace TestApp1
{
[ComVisible(true)]
public class Controller
{
private WebView2 View { get; set; }
public Controller(WebView2 view)
{
View = view;
}
public void PostWebMessageAsString(string webMessageAsString)
{
this.View.CoreWebView2.PostWebMessageAsString(webMessageAsString);
}
public void PostWebMessageAsJson(string webMessageAsJson)
{
this.View.CoreWebView2.PostWebMessageAsJson(webMessageAsJson);
}
public async Task<string> ExecuteScriptAsync(string script)
{
//フォームから呼び出されるコントローラーなので、同期コンテキストに戻らないようにする。
return await this.View.ExecuteScriptAsync(script).ConfigureAwait(false);
}
}
}
WebView2をホストしているフォームに、Controllerを追加します。
また、EnsureCoreWebView2Asyncより後にNavigationCompletedイベントを登録します。
namespace TestApp1
{
public partial class Form1 : Form
{
private Controller Controller;
public Form1()
{
InitializeComponent();
this.WebView2.CoreWebView2InitializationCompleted += WebView2_CoreWebView2InitializationCompleted;
}
protected override async void OnLoad(EventArgs e)
{
var environment = await CoreWebView2Environment.CreateAsync(null, System.IO.Directory.GetCurrentDirectory());
await this.WebView2.EnsureCoreWebView2Async(environment);
this.WebView2.NavigationCompleted += WebView2_NavigationCompleted;
base.OnLoad(e);
}
private void WebView2_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
{
if (e.IsSuccess)
{
//ControllerのViewプロパティに、Form1のWebView2を登録するのが目的。
this.Controller = new Controller(this.WebView2);
this.WebView2.CoreWebView2.Navigate(@"D:\index.html");
}
}
private void WebView2_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
}
}
}
前述した3つのメソッドを作成したので、実際に試してみます。
①PostWebMessageAsStringで文字列を送信
ここではテストだけの為に、NavigationCompletedの発生時に送信しています。
殆どの場合は、Formのボタンクリック等のイベントで送信する事になると思います。
NavigationCompletedイベントの発生以降にPostMessageを実行する理由は、JavaScript等のコンテンツの読み込みの完了を待つ必要があるからです。
WebView2 アプリのナビゲーション イベント
private void WebView2_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
if (e.IsSuccess)
{
this.Controller.PostWebMessageAsString("★テストメッセージ★");
}
}
index.html側では、JavaScriptのmessageイベントで受け取ります。
<body>
<meter id="meter" min="0" max="100" value="0"></meter>
<br />
<select id="language_select"></select>
<script>
window.chrome.webview.addEventListener('message', event => {
alert("受信したメッセージ: " + event.data);
});
</script>
</body>
②PostWebMessageAsJsonでJSON文字列を送信
C#(Form1)の送信処理は下記です。
private void WebView2_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
if (e.IsSuccess)
{
var lang = new{ Name = "C#", FirstRelease = 2002 };
this.Controller.PostWebMessageAsJson(JsonSerializer.Serialize(lang));
}
}
JavaScript側では、stringifyしてからparseするとJSONオブジェクトとして取り扱えます。
<script>
window.chrome.webview.addEventListener('message', event => {
const jsonString = JSON.stringify(event.data);
const obj = JSON.parse(jsonString);
alert(obj.Name);
});
</script>
③ExecuteScriptAsyncでJavaScriptの関数を実行する。
(ついでに戻り値も取得する。)
JavaScriptのmyFunc関数を呼び出しています。
戻り値が必要な場合、JavaScriptでreturnします。
ExecuteScriptAsyncの戻り値は常にJSON文字列なので、C#でDeserializeが必要です。
戻り値が文字列の場合
private async void WebView2_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
if (e.IsSuccess)
{
string data = "あいうえお";
//JavaScriptのmyFunc関数を直接呼び出している。
//myFuncに文字列として渡したいので、myFuncの引数を''(シングルクォート)で囲んでいる。
string str = await this.Controller.ExecuteScriptAsync($"myFunc('{data}')");
//戻り値strの値はダブルクォーテーションがあるJSON「"あいうえおかきくけこ"」なので、
//デシリアライズして、「あいうえおかきくけこ」にする。
str = JsonSerializer.Deserialize<string>(str);
MessageBox.Show(str);
}
}
<script>
function myFunc(val) {
return val + "かきくけこ";
}
</script>
戻り値が数値の場合
private async void WebView2_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
if (e.IsSuccess)
{
int data = 10;
//JavaScriptのmyFunc関数を直接呼び出している。
//myFuncに数値として渡したいので、myFuncの引数を''(シングルクォート)で囲んでいない。
//戻り値strの値は「100」(string型)
string str = await this.Controller.ExecuteScriptAsync($"myFunc({data})");
//数値として使用したければデシリアライズする。
int i = JsonSerializer.Deserialize<int>(str);
//MessageBoxで表示する為に文字列に戻している。
MessageBox.Show(i.ToString());
}
}
<script>
function myFunc(val) {
return val*10;
}
</script>
ここまで、C#からWebViewへのメッセージの送信方法でした。
6.JavaScriptからC#へのデータ送信
今度はJavaScriptからメッセージを送信してC#で受信する処理です。
方法は3つあります。
| JavaScriptからの送信方法 | C#側の受信方法 | |
|---|---|---|
| 1 | window.chrome.webview.postMessage(文字列) | WebMessageReceivedで受信 |
| 2 | window.chrome.webview.postMessage(JSON) | WebMessageReceivedで受信 必要ならデシリアライズする |
| 3 | JavaScriptでC#のメソッドを実行する。 | 不要 |
①JavaScriptのwindow.chrome.webview.postMessageで文字列を送信し、C#のWebMessageReceivedで受信する。
JSのpostMessageからのメッセージを受信する為に、WebMessageReceivedを登録します。
タイミングは、EnsureCoreWebView2Asyncの直後にしています。
namespace TestApp1
{
public partial class Form1 : Form
{
private Controller Controller;
public Form1()
{
InitializeComponent();
this.WebView2.CoreWebView2InitializationCompleted += WebView2_CoreWebView2InitializationCompleted;
}
protected override async void OnLoad(EventArgs e)
{
var environment = await CoreWebView2Environment.CreateAsync(null, System.IO.Directory.GetCurrentDirectory());
await this.WebView2.EnsureCoreWebView2Async(environment);
this.WebView2.NavigationCompleted += WebView2_NavigationCompleted;
this.WebView2.WebMessageReceived += WebView2_WebMessageReceived;
base.OnLoad(e);
}
private void WebView2_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
{
if (e.IsSuccess)
{
this.Controller = new Controller(this.WebView2);
this.WebView2.CoreWebView2.Navigate(@"D:\index.html");
}
}
private void WebView2_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
}
private void WebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
{
MessageBox.Show(e.TryGetWebMessageAsString());
}
}
}
<script>
window.addEventListener("load", () => {
window.chrome.webview.postMessage("JavaScriptからの送信テスト");
});
</script>
②JavaScriptのwindow.chrome.webview.postMessageでJSON文字列を送信し、C#のWebMessageReceivedで受信する。
必要であれば、JsonSerializer.Deserialize でC#のオブジェクトに変換する。
private void WebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
{
Lang lang = JsonSerializer.Deserialize<Lang>(e.WebMessageAsJson);
MessageBox.Show(lang.Name);
}
class Lang
{
public string Name { get; set; }
public int FirstRelease { get; set; }
}
<script>
window.addEventListener("load", () => {
window.chrome.webview.postMessage({ "Name": "C#", "FirstRelease":2002});
});
</script>
③JavaScriptからC#のメソッドを呼び出す。
まずは、JavaScriptから呼び出したいメソッドをControllerに追加する。
public class Controller
{
public void TestMethod(string msg)
{
MessageBox.Show(msg);
}
}
次に、WebView2.CoreWebView2.AddHostObjectToScript で、Controllerオブジェクトを、Controller1 という名前でWebView2に登録する。
public class Form1
{
private Controller Controller;
private void WebView2_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
{
if (e.IsSuccess)
{
this.Controller = new Controller(this.WebView2);
this.WebView2.CoreWebView2.AddHostObjectToScript("Controller1", this.Controller);
this.WebView2.CoreWebView2.Navigate(@"D:\index.html");
}
}
}
JavaScript側で、chrome.webview.hostObjects を介して呼び出す。
<script>
window.addEventListener("load", () => {
chrome.webview.hostObjects.Controller1.TestMethod("てすと");
});
</script>
結果、JavaScriptからC#のメソッドを呼び出せました。

役に立ちそうな資料
- WebView2 アプリのナビゲーション イベント
-
ネイティブ側コードから Web 側コードを呼び出す
※ExecuteScriptAsyncの戻り値のstringがJSONであると明記されている。 - WebView2 アプリからの印刷
- コンテキストメニューのカスタマイズ







