Web ビュー

Web ビュー コントロールは、Microsoft Edge 従来版のレンダリング エンジンを使って、Web コンテンツをレンダリングするアプリにビューを埋め込みます。 また、Web ビュー コントロールでは、ハイパーリンクの表示と動作が可能です。

重要

WebView2 コントロールは、WinUI3 の一部として利用できます。 WebView2 は、Microsoft Edge (Chromium) をレンダリング エンジンとして使用して、Web コンテンツをアプリに表示します。 詳細については、WinUI API リファレンスの「Microsoft Edge WebView2 の概要」、「WinUI 3 の WebView2 の使用を開始する (プレビュー)」、および WebView2 に関するページを参照してください。

これは適切なコントロールですか?

リモート Web サーバー、動的に生成されたコード、またはアプリ パッケージのコンテンツ ファイルの、書式がリッチな HTML コンテンツを表示するには、Web ビュー コントロールを使います。 また、リッチ コンテンツは、スクリプト コードを含めることができ、さらに、スクリプトとアプリのコード間で通信を行うこともできます。

推奨事項

  • 読み込まれた Web サイトがデバイスに応じて正しく書式設定されており、アプリの他の部分と一貫性のある色、文字体裁、ナビゲーションが使われていることを確認します。
  • 入力フィールドのサイズを適切に調整する必要があります。 テキストを入力する際にズームインできることにユーザーが気付かない場合があります。
  • Web ビューがアプリの他の部分とは異なって見える場合は、関連タスクを実行するための代替のコントロールまたは手段を検討します。 Web ビューがアプリの他の部分にマッチしていると、すべてが 1 つのシームレスなエクスペリエンスとしてユーザーに認識してもらえます。

Web ビューを作成する

Web ビューの外観を変更する

WebView は、Control サブクラスではないため、コントロール テンプレートがありません。 ただし、さまざまなプロパティを設定して、Web ビューのビジュアル要素の一部を制御することはできます。

  • 表示領域を制限するには、Width プロパティと Height プロパティを設定します。
  • Web ビューの変換、拡大縮小、傾斜、そして回転には、RenderTransform プロパティを使います。
  • Web ビューの不透明度を調整するには、Opacity プロパティを設定します。
  • HTML コンテンツが色を指定していないときに、Web ページの背景として色を指定するには、DefaultBackgroundColor プロパティを設定します。

Web ページのタイトルを取得する

DocumentTitle プロパティを使うと、現在 Web ビューに表示されている HTML ドキュメントのタイトルを取得することができます。

入力イベントとタブ オーダー

WebView は Control サブクラスではありませんが、キーボードの入力フォーカスを受け取って、タブ順に関与します。 ただし、Focus メソッド、そして GotFocus イベントと LostFocus イベントを提供しますが、タブ関連のプロパティはありません。 タブ順での位置は、XAML ドキュメントの順序での位置と同じです。 タブ順には、入力フォーカスを受け取ることができる Web ビューのコンテンツの要素がすべて含まれています。

WebView クラスのページの「Event」表からもわかるとおり、Web ビューは、KeyDownKeyUpPointerPressed といった UIElement から継承されたユーザー入力イベントのほとんどをサポートしていません。 その代わり、InvokeScriptAsync を JavaScript の eval 関数と共に使って、HTML イベント ハンドラーを利用したり、HTML イベント ハンドラーの window.external.notify を通じて WebView.ScriptNotify に対応するアプリに通知したりできます。

Web ビューには、基本的なナビゲーション用の API (GoBackGoForwardStopRefreshCanGoBackCanGoForward) がいくつか用意されています。 これらを使うと、一般的な Web 閲覧機能をアプリに追加できます。

Web ビューの初期コンテンツを設定するには、XAML の Source プロパティを使います。 XAML パーサーは文字列を Uri に自動的に変換します。

<!-- Source file is on the web. -->
<WebView x:Name="webView1" Source="http://www.contoso.com"/>

<!-- Source file is in local storage. -->
<WebView x:Name="webView2" Source="ms-appdata:///local/intro/welcome.html"/>

<!-- Source file is in the app package. -->
<WebView x:Name="webView3" Source="ms-appx-web:///help/about.html"/>

Source プロパティはコードで設定できますが、それよりも Navigate メソッドの 1 つを使ってコードにコンテンツを読み込むほうがよいでしょう。

Web コンテンツを読み込むには、Navigate メソッドを http または https スキームを使う Uri と共に用います。

webView1.Navigate(new Uri("http://www.contoso.com"));

POST 要求と HTTP ヘッダーを有する URI へと移動するには、NavigateWithHttpRequestMessage メソッドを使います。 このメソッドは、HttpRequestMessage.Method プロパティの値として HttpMethod.PostHttpMethod.Get のみをサポートします。

圧縮されておらず、暗号化もされていないコンテンツをアプリの LocalFolder データ ストアまたは TemporaryFolder データ ストアから読み込むには、Navigate メソッドを、ms-appdata スキームを使う Uri と共に用います。 このスキームを Web ビューがサポートするには、ローカル フォルダーまたは一時フォルダーの下にサブフォルダーを設け、そこにコンテンツを配置する必要があります。 これにより、「ms-appdata:///local/フォルダー/ファイル.html」や「ms-appdata:///temp/フォルダー/ファイル.html」といった URI への移動が可能になります (圧縮され、暗号化されたファイルを読み込む場合は、NavigateToLocalStreamUri に関するページをご覧ください)。

これらの第 1 レベルのサブフォルダーは、他の第 1 レベルのサブフォルダー内のコンテンツから分離されます。 たとえば「ms-appdata:///temp/folder1/file.html」に移動はできますが、このファイル内のリンクに「ms-appdata:///temp/folder2/file.html」は指定できません。 ただし、ms-appx-web スキームを使ってアプリ パッケージの HTML コンテンツにリンクしたり、http または https の URI スキームを使って Web コンテンツにリンクしたりすることはできます。

webView1.Navigate(new Uri("ms-appdata:///local/intro/welcome.html"));

アプリ パッケージからコンテンツを読み込むには、Navigate メソッドを ms-appx-web スキームを使った Uri と共に用います。

webView1.Navigate(new Uri("ms-appx-web:///help/about.html"));

NavigateToLocalStreamUri メソッドを使えば、カスタム リゾルバーを通じてローカルのコンテンツを読み込めます。 これにより、Web ベースのコンテンツをオフライン用にダウンロードしたりキャッシュしたり、圧縮ファイルからコンテンツを抽出したりといった高度なシナリオも可能です。

ナビゲーション イベントを処理する

Web ビュー コントロールでは、ナビゲーションやコンテンツの読み込みの状態に対する処理に使うことができるイベントがいくつか用意されています。 ルート Web ビュー コンテンツのイベントは、NavigationStartingContentLoadingDOMContentLoadedNavigationCompleted の順に発生します。

NavigationStarting - Web ビューが新しいコンテンツに移動する前に発生します。 WebViewNavigationStartingEventArgs.Cancel プロパティを "true" に設定することで、このイベントのハンドラーで移動をキャンセルできます。

webView1.NavigationStarting += webView1_NavigationStarting;

private void webView1_NavigationStarting(object sender, WebViewNavigationStartingEventArgs args)
{
    // Cancel navigation if URL is not allowed. (Implementation of IsAllowedUri not shown.)
    if (!IsAllowedUri(args.Uri))
        args.Cancel = true;
}

ContentLoading - Web ビューが新しいコンテンツの読み込みを開始すると発生します。

webView1.ContentLoading += webView1_ContentLoading;

private void webView1_ContentLoading(WebView sender, WebViewContentLoadingEventArgs args)
{
    // Show status.
    if (args.Uri != null)
    {
        statusTextBlock.Text = "Loading content for " + args.Uri.ToString();
    }
}

DOMContentLoaded - Web ビューが現在の HTML のコンテンツの解析を完了すると発生します。

webView1.DOMContentLoaded += webView1_DOMContentLoaded;

private void webView1_DOMContentLoaded(WebView sender, WebViewDOMContentLoadedEventArgs args)
{
    // Show status.
    if (args.Uri != null)
    {
        statusTextBlock.Text = "Content for " + args.Uri.ToString() + " has finished loading";
    }
}

NavigationCompleted - Web ビューが現在のコンテンツの読み込みを完了したとき、またはナビゲーションが失敗したときに発生します。 ナビゲーションが失敗したかどうかを判断するには、WebViewNavigationCompletedEventArgs クラスの IsSuccess プロパティと WebErrorStatus プロパティを確認します。

webView1.NavigationCompleted += webView1_NavigationCompleted;

private void webView1_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
{
    if (args.IsSuccess == true)
    {
        statusTextBlock.Text = "Navigation to " + args.Uri.ToString() + " completed successfully.";
    }
    else
    {
        statusTextBlock.Text = "Navigation to: " + args.Uri.ToString() +
                               " failed with error " + args.WebErrorStatus.ToString();
    }
}

Web ビューのコンテンツの各 iframe についても、同様のイベントが同じ順序で発生します。

  • FrameNavigationStarting - Web ビューのフレームが新しいコンテンツに移動する前に発生します。
  • FrameContentLoading - Web ビューのフレームが新しいコンテンツの読み込みを開始すると発生します。
  • FrameDOMContentLoaded - Web ビューのフレームが現在の HTML のコンテンツの解析を完了すると発生します。
  • FrameNavigationCompleted - Web ビューのフレームがコンテンツの読み込みを完了すると発生します。

潜在的な問題に対処する

長時間実行されているスクリプトや、Web ビューが読み込めないコンテンツ、安全でないコンテンツに関する警告など潜在的な問題があれば、それに対処することができます。

スクリプトを実行中にアプリが応答しないような場合があったとします。 Web ビューにより JavaScript が実行され、スクリプトを中断する機会が提供される際に、LongRunningScriptDetected イベントが定期的に発生します。 スクリプトがどれくらいの時間実行されているか調べるには、WebViewLongRunningScriptDetectedEventArgsExecutionTime プロパティを確認します。 スクリプトを停止するには、イベント引数の StopPageScriptExecution プロパティを true に設定します。 停止されたスクリプトは、以降の Web ビューのナビゲーションでもう一度読み込まれるまで、再実行されません。

Web ビュー コントロールは、任意のファイルの種類をホストすることができません。 Web ビューでホストできないコンテンツを読み込もうすると、UnviewableContentIdentified イベントが発生します。 このイベントを処理してユーザーに通知することも、Launcher クラスを使ってファイルを外部のブラウザーまたは別のアプリにリダイレクトすることもできます。

同様に、fbconnect:// や mailto:// といったサポートされていない URI スキームが Web コンテンツで呼び出されると、UnsupportedUriSchemeIdentified イベントが発生します。 既定のシステム起動プログラムに URI を起動させるのではなく、このイベントを処理してカスタム動作を定義してもよいでしょう。

Web ビューによって、SmartScreen フィルターにより安全でないと報告されているコンテンツの警告ページが表示されると、UnsafeContentWarningDisplayingevent イベントが発生します。 ユーザーがナビゲーションの続行を選んだ場合は、そのページへの移動では以降、警告が表示されたり、イベントが発されたりすることはありません。

Web ビューのコンテンツの特殊ケースを処理する

ContainsFullScreenElement プロパティと ContainsFullScreenElementChanged イベントを使うと、全画面での動画の再生といった、全画面表示を可能にしたり、検出したり、または処理したりすることができます。 たとえば、ContainsFullScreenElementChanged イベントを使えば、Web ビューのサイズを変更して、アプリ ビュー全体を占有することができます。もしくは、次の例で示すとおり、Web の全画面表示が望ましいときは、ウィンドウ内のアプリを全画面表示にすることもできます。

// Assume webView is defined in XAML
webView.ContainsFullScreenElementChanged += webView_ContainsFullScreenElementChanged;

private void webView_ContainsFullScreenElementChanged(WebView sender, object args)
{
    var applicationView = ApplicationView.GetForCurrentView();

    if (sender.ContainsFullScreenElement)
    {
        applicationView.TryEnterFullScreenMode();
    }
    else if (applicationView.IsFullScreenMode)
    {
        applicationView.ExitFullScreenMode();
    }
}

NewWindowRequested イベントを使えば、たとえばポップアップ ウィンドウのように、ホストされている Web コンテンツによって新しいウィンドウの表示が要求されるようなケースに対処できます。 別の WebView コントロールで、要求されたウィンドウのコンテンツを表示することもできます。

特別な機能を必要とする Web 機能を有効にするには、PermissionRequested イベントを使います。 現在、これらには位置情報、IndexedDB ストレージ、ユーザーのオーディオやビデオ (たとえば、マイクまたは Web カメラの機能) があります。 アプリがユーザーの位置情報またはユーザーのメディアにアクセスする場合も、アプリのマニフェストでそうした機能を宣言する必要があります。 たとえば、位置情報を使うアプリでは少なくとも Package.appxmanifest で次の機能の宣言が必要です。

  <Capabilities>
    <Capability Name="internetClient" />
    <DeviceCapability Name="location" />
  </Capabilities>

アプリによる PermissionRequested イベントの処理に加えて、これらの機能を有効にするには、位置情報やメディアの機能を要求するアプリに関する、標準的なシステム ダイアログをユーザーが承認する必要があります。

次の例は、アプリによって Bing のマップで位置情報がどのように有効されるかを示しています。

// Assume webView is defined in XAML
webView.PermissionRequested += webView_PermissionRequested;

private void webView_PermissionRequested(WebView sender, WebViewPermissionRequestedEventArgs args)
{
    if (args.PermissionRequest.PermissionType == WebViewPermissionType.Geolocation &&
        args.PermissionRequest.Uri.Host == "www.bing.com")
    {
        args.PermissionRequest.Allow();
    }
}

アプリが許可の要求に応答するにあたってユーザーの入力をはじめ非同期の操作を要求する場合は、WebViewPermissionRequestDefer メソッドを使い、後で処理できる WebViewDeferredPermissionRequest を作成します。 WebViewPermissionRequest.Defer に関するページをご覧ください。

Web ビューでホストされている Web サイトからユーザーが安全にログアウトしなければならない場合や、セキュリティが重要であるような場合は、静的メソッドである ClearTemporaryWebDataAsync を呼び出し、当該の Web ビュー セッションでローカルにキャッシュされたコンテンツをすべて消去します。 これにより、悪意あるユーザーが重要なデータにアクセスするのを防ぎます。

Web ビューのコンテンツとインタラクトする

InvokeScriptAsync メソッドで Web ビューのコンテンツにスクリプトを呼び出し、または挿入して、ScriptNotify イベントで Web ビューのコンテンツから情報を反対に取得することで、Web ビューのコンテンツとインタラクトできます。

Web ビューのコンテンツ内で JavaScript を呼び出すには、InvokeScriptAsync メソッドを使います。 呼び出されたスクリプトは、文字列型の値のみを返すことができます。

たとえば、webView1 という名前の Web ビューのコンテンツに、3 つのパラメーターを要する setDate という名前の関数が含まれている場合は、次のように呼び出すことができます。

string[] args = {"January", "1", "2000"};
string returnValue = await webView1.InvokeScriptAsync("setDate", args);

InvokeScriptAsync を JavaScript の eval 関数と共に使って、Web ページにコンテンツを挿入します。

ここでは、XAML のテキスト ボックス (nameTextBox.Text) のテキストは、webView1 でホストされている HTML ページの div に書き込まれます。

private async void Button_Click(object sender, RoutedEventArgs e)
{
    string functionString = String.Format("document.getElementById('nameDiv').innerText = 'Hello, {0}';", nameTextBox.Text);
    await webView1.InvokeScriptAsync("eval", new string[] { functionString });
}

Web ビューのコンテンツのスクリプトでは、window.external.notify を文字列型パラメーターと共に使って、情報をアプリに戻せます。 これらのメッセージを受け取るには、ScriptNotify イベントを処理します。

外部の Web ページを有効にして、window.external.notify を呼び出した際に ScriptNotify イベントを発生させるには、当該のページの URI をアプリの宣言の ApplicationContentUriRules セクションに含める必要があります (これは、Package.appxmanifest デザイナーの [コンテンツ URI] タブの Microsoft Visual Studio で行うことができます)。この一覧の URI は HTTPS を使用する必要があり、サブドメインメイン ワイルドカード (たとえば https://*.microsoft.com) を含めることができますが、ドメインメイン ワイルドカード (例: https://*.com および https://*.*) を含めることはできません。 マニフェスト要件は、アプリ パッケージから生成されたコンテンツには適用されず、ms-local-stream:// URI を使うか、NavigateToString を使って読み込まれるかのいずれかです。

Web ビューの Windows ランタイムにアクセスする

AddWebAllowedObject メソッドを使うと、Windows ランタイム コンポーネントから Web ビューの JavaScript コンテンツにネイティブ クラスのインスタンスを挿入できます。 これにより、その Web ビューの JavaScript コンテンツにあるオブジェクトの、ネイティブのメソッドやプロパティ、イベントにフル アクセスできるようになります。 クラスは、AllowForWeb 属性で修飾される必要があります。

たとえば、次のコードでは、Windows ランタイム コンポーネントからインポートされた MyClass のインスタンスが Web ビューに挿入されます。

private void webView_NavigationStarting(WebView sender, WebViewNavigationStartingEventArgs args)
{
    if (args.Uri.Host == "www.contoso.com")
    {
        webView.AddWebAllowedObject("nativeObject", new MyClass());
    }
}

詳しくは、WebView.AddWebAllowedObject に関するページをご覧ください。

さらに、Web ビューの信頼できる JavaScript コンテンツでは、Windows ランタイム API に直接アクセスすることも許可されています。 これにより、Web ビューでホストされている Web アプリの強力なネイティブ機能が利用できます。 この機能を有効にするには、WindowsRuntimeAccess を "all" に設定して、信頼できるコンテンツの URI を Package.appxmanifest のアプリの ApplicationContentUriRules の許可リストに載せる必要があります。

この例は、アプリ マニフェストのセクションを示しています。 ここでは、ローカル URI が Windows ランタイムへのアクセスを与えられます。

  <Applications>
    <Application Id="App"
      ...

      <uap:ApplicationContentUriRules>
        <uap:Rule Match="ms-appx-web:///Web/App.html" WindowsRuntimeAccess="all" Type="include"/>
      </uap:ApplicationContentUriRules>
    </Application>
  </Applications>

Web コンテンツのホスティングのオプション

WebView.Settings プロパティ (WebViewSettings 型のプロパティ) を使うと、JavaScript と IndexedDB のオン/オフをコントロールできます。 たとえば、Web ビューで完全に静的なコンテンツを表示するような場合は、JavaScript を無効にすることでパフォーマンスを高められます。

Web ビューのコンテンツをキャプチャする

Web ビューのコンテンツを他のアプリと共有できるようにするには、CaptureSelectedContentToDataPackageAsync メソッドを使います。このメソッドは、DataPackage として選択したコンテンツを返します。 このメソッドは非同期であるため、DataRequested イベント ハンドラーが、非同期呼び出しが完了する前に戻されてしまうのを防ぐために、遅延を使用する必要があります。

Web ビューの現在のコンテンツに関するプレビュー イメージを取得するには、CapturePreviewToStreamAsync メソッドを使います。 このメソッドは、現在のコンテンツのイメージを作成し、指定のストリームに書き込みます。

スレッド処理の動作

既定では、Web ビューのコンテンツは、デスクトップ デバイス ファミリのデバイス上の UI スレッドにホストされており、その他のデバイス上の UI スレッドからは分離されています。 WebView.DefaultExecutionMode 静的プロパティを使うと、現在のクライアントに対する既定のスレッド処理動作を照会できます。 必要であれば、WebView(WebViewExecutionMode) コンストラクターを使ってその動作をオーバーライドすることもできます。

モバイル デバイスの UI スレッドでコンテンツをホストしている場合は、パフォーマンス上の問題が発生する可能性があります。DefaultExecutionMode を変更するときは、対象となるすべてのデバイスを必ずテストしてください。

UI スレッドから外れてコンテンツをホストしている Web ビューは、FlipViewScrollViewer といった、Web ビューのコントロールから親へと伝達するジェスチャを必要とする親コントロールや、その他の関連コントロールと互換性がありません。 そうしたコントロールは、オフスレッドの Web ビューで開始されるジェスチャを受け取ることができません。 さらに、オフスレッドの Web コンテンツの出力は、直接サポートされていません。つまり、要素は WebViewBrush フィルで代わりに出力することになります。

サンプル コードの入手