酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

WebBrowserコントロールでローカルのコンテンツを表示する

ヘルプページや「このアプリケーションについて」のページをアプリ内に格納しておいてインターネットの繋がっていない場合でも、HTMLファイルを表示出来るようにしたいという要望があります。対応としては2つの対応方法があります。

  • 文字列のhtmlを表示する方法
  • 分離ストレージへhtmlファイルを格納して表示する方法

日本人的には前者の方法はおススメ出来ません。後者択一になると思います。理由は後述します。

WebBrowser.NavigateToStringメソッドで文字列のhtmlを表示する

string型のhtmlをパラメータに、WebBrowser.NavigateToStringメソッドを使うことが出来ます。

ソリューションエクスプローラーで簡単なHTMLファイルを追加しておきます。名前は「About.html」にしています。

<html>
  <head></head>
  <body>
  テストページです。
  </body>
</html>

App.GetResourceStreamメソッドでアプリケーションパッケージ内のリソースファイルを読み出します。

using System;
using System.IO;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;

namespace WebBrowserLocalResourceTest {
    public partial class MainPage : PhoneApplicationPage {
        // コンストラクター
        public MainPage() {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e) {

            // パッケージからhtmlファイルを読み出す
            var appRes = App.GetResourceStream(new Uri("About.html", UriKind.Relative));
            using (var reader = new StreamReader(appRes.Stream)) {
                var html = reader.ReadToEnd();
                
                //<html>
                //  <head></head>
                //  <boby>
                //  テストページです。
                //  </body>
                //</html>
                webBrowser.NavigateToString(html);
            }
        }
    }
}

これを実行してみましょう。

単純に文字列を渡して表示させただけですと日本語が文字化けしてしまいます。これはあらかじめhtmlの日本語を文字実体参照しておくことで回避が可能です。以下のhtmlは「テストページです。」を実体参照変換させています。

<html>
  <head></head>
  <body>
  &#12486;&#12473;&#12488;&#12506;&#12540;&#12472;&#12391;&#12377;&#12290;
  </body>
</html>

実体参照変換後に実行すると、問題なく表示出来ます。

更にどうでも良いネタですが、headタグがないと空白のドキュメント("about:blank")が表示されてしまうので気をつけましょう。

あと、NavigateToStringメソッドで表示させたHTMLからローカルファイルにアクセス出来ませんので、画像データなどに関してはData URI Schemeを使用する必要があります*1

WebBrowser.Baseプロパティを使って分離ストレージのhtmlを表示する

WebBrowserコントロールは、分離ストレージに保存したhtmlファイルを参照することが可能です。

相対参照を行う基本ディレクトリを設定するWebBrowser.Baseプロパティがあります。WebBrowser.Baseプロパティは分離ストレージのディレクトリを指定することが出来ます。

ソリューションエクスプローラーで簡単なHTMLファイルを追加しておきます。名前は「About.html」にしています。

<html>
  <head></head>
  <body>
  テストページです。
  </body>
</html>

ここではWebBrowserコントロールの基本ディレクトリを「help」にして、分離ストレージ内の「help/About.html」を参照させます。

using System;
using System.IO;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using System.IO.IsolatedStorage;

namespace WebBrowserLocalResourceTest {
    public partial class MainPage : PhoneApplicationPage {
        // コンストラクター
        public MainPage() {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e) {
            using (var store = IsolatedStorageFile.GetUserStoreForApplication()) {
                // helpディレクトリを作成する
                if (!store.DirectoryExists("help")) {
                    store.CreateDirectory("help");
                }

                // パッケージからhtmlファイルのリソースを読み出す
                var appRes = App.GetResourceStream(new Uri("About.html", UriKind.Relative));

                // ストリームからhtmlの内容を読み出す
                byte[] bytes = new byte[appRes.Stream.Length];
                using (var strm = appRes.Stream) {
                    strm.Read(bytes, 0, bytes.Length);
                }
                // 分離ストレージへhtmlを書き出す
                using (var strm = store.OpenFile("help/About.html", FileMode.Create)) {
                    strm.Write(bytes, 0, bytes.Length);
                }
            }

            // 基本ディレクトリを設定
            webBrowser.Base = "help";
            // 基本ディレクトリからの相対パスでAbout.htmlへ遷移
            webBrowser.Navigate(new Uri("About.html", UriKind.Relative));
        }
    }
}

きちんと分離ストレージ内のデータが表示されましたでしょうか。

*1:情報提供: [http://twitter.com/#!/mikiofuku/status/135949274704904192:title=@mikiofuku]