何となく Blog by Jitta
Microsoft .NET 考

目次

Blog 利用状況
  • 投稿数 - 761
  • 記事 - 18
  • コメント - 35955
  • トラックバック - 222
ニュース
  • IE7以前では、表示がおかしい。div の解釈に問題があるようだ。
    IE8の場合は、「互換」表示を OFF にしてください。
  • 検索エンジンで来られた方へ:
    お望みの情報は見つかりましたか? よろしければ、コメント欄にどのような情報を探していたのか、ご記入ください。
It's ME!
  • はなおか じった
  • 世界遺産の近くに住んでます。
  • Microsoft MVP for Visual Developer ASP/ASP.NET 10, 2004 - 9, 2011
広告

記事カテゴリ

書庫

日記カテゴリ

ギャラリ

その他

わんくま同盟

同郷

 

会社の、新技術キャッチアップ プロジェクトで調べたことをお送りしてきた Silverlight 奮戦記ですが、このたび、成果発表会が行われることになりました。

発表時間はごくわずかなので、デモを中心に「こんなことが出来ます」を、Google Web Toolkit、Adobe Integrated Runtime, Silverlight で行うことになったのですが、Silverlight で担当するのが、以前に Windows Application として作成した、「任意の絵をバックグラウンドにして設備管理をする」アプリケーションの、「任意の絵をバックグラウンドにする」の部分となりました!!わーわーわー!!って、喜んでる場合じゃねーよorz

Windows Application の場合、ローカルにあるファイルに、ローカル アプリケーションがアクセスすることになります。何も難しいことはありません。

Silverlight の場合、ローカルにあるファイルにアクセスできないはずなので、一旦 ASP.NET 等でサーバーにアップロードし、Silverlight アプリケーションがダウンロードして使用する、という形になります。

ということは、Silverlight 単体では出来ない、ということです。ASP.NET 他、他の Web Application とのコンビネーションになります。


まずは、開発環境から。β1の頃に書いたけど、RTM しているので、RTM バージョンということで。

Visual Studio 2008 Standard Edition 以上を用意します。それに、Service Pack 1 をあてます。場合によっては、SP1 準備ツールとかいうものを適用しておく必要があるかもしれません。SP1 をあてたら、インテリセンスが英語になってしまう不具合があるので、それを解消するパッチをあてます。

次、Silverlight 本体。「開発環境なんざいらねぇぜ。テキスト エディタとコンパイラで作ってやるぜ!」という強者は、Visual Studio も要りません。Silverlight SDK のみを。普通の方は、Visual Studio 2008 SP1 用 Silverlight Tools を、ダウンロードします。

また、Silverlight2 のドキュメントが、CHM 形式でダウンロードできます。一応、Visual Studio の Document Explorer にインテグレートされますが、[F1] 等で参照しようとすると、高確率で WPF のヘルプが出てきます。Silverlight の CHM ファイルを検索すれば、Silverlight のものしか出てきませんので、検索するときには CHM ファイルのほうが便利だと思います。

MSDN ライブラリには、オンラインのドキュメントも、用意されています。

以上、環境整備終わり。


それではまず、下準備。これ、とっても重要。

上に「Silverlight の場合、ローカルにあるファイルにアクセスできないはず」とか書いたけど、そうなんだっけ?ってことで、「silverlight file upload」で検索すると、CodePlex に Silverlight File Upload というコントロールが見つかった。じゃぁ、こいつはどうやってローカル ファイルにアクセスしているんだろう?ってんで MSDN を調べると、OpenFileDialog クラスが見つかった。これでローカル ファイルにアクセスすることが出来る。

では、画像の表示。Windows Application では、Bitmap クラスを使用する。Silverlight ではどうかというと、そもそも System.Drawing 名前空間がない。では、他には?と探す…のは面倒なので、CHM ファイルで「Bitmap」を検索する。すると、Syste.Windows.Interop 名前空間に、HostingRenderTargetBitmap クラスというのが見つかる。でもこれにはアプリケーション コードでこのメンバを使用すると、MethodAccessException 例外がスローされます。などと書いてあるので、使えない。次、次。「目次」の「ビジュアル デザイン」を開くと、「グラフィクス」という項目がある。ここの中に「イメージング」があるので、これを開く。すると、イメージを描画するには、Image オブジェクトまたは ImageBrush オブジェクトを使用します。とある。Image クラスの説明には、BitmapImage クラスへのリンクもある。このふたつのクラスについて、調べる。すると、Image クラスはインターネットの向こうからしかイメージを取得できない。BitmapImage クラスも同じ。・・・困った。せっかく、ローカル ファイルへのパスがわかっても、そこから画像オブジェクトを作成することが出来ない。分離ストレージに放り込んで、そこからストリームで画像を作成してやろうかと思っていたのだけれど、メモリ上で画像を扱えないのではこの方法は使えない。

困った。。。

じゃぁ、あれだ。他のウェブ アプリケーションでサーバーにファイルをアップロードして、そいつを特定の名前で XAP ファイルと同じディレクトリにおいて、Silverlight からはそのファイルを参照すればいい、ってことですね。


決まったので、次、プロジェクトを作成する。

Visual Studio 2008 を起動する。新しいプロジェクトを作成する。とりあえず、ソリューション名を「SilverlightDemo」、プロジェクト名を「BackgroundMap」とする。

すると、Silverlight アプリケーションをホストするものをどうするか、聞いてくる。先にも書いたように、どうにかして、サーバーにファイルをアップロードしなければならない。なので、ウェブ アプリケーションを作成することにする。すると、「BackgroundMap.Web」という名前の ASP.NET アプリケーションが作成される。

ちょい見すると、「BackgroundMapTestPage.aspx」というページが作られている。この中に、Silverlight をホストするコードが書かれている。しかし、このページにはビハインド コードがない。そこで、ホストするためのコードを Default.aspx にコピーして、デバッグのスタート ページも Default.aspx に変更する。

コピーした、Silverlight をホストするコード
<%@ Register Assembly="System.Web.Silverlight"
    Namespace="System.Web.UI.SilverlightControls" TagPrefix="asp" %>
(飛ばして)
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <div style="height: 100%;">
        <asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/BackgroundMap.xap"
            MinimumVersion="2.0.31005.0" Width="100%" Height="100%" />
    </div>

さて、サーバーにファイルをアップロードして、どこかに保存しておくコードを作る。

FileUpload コントロールと、ポストバックを発生させるための Button コントロール、エラーが発生したときにメッセージを表示する Label コントロールを追加する。

FileUpload コントロールの説明を参照すると、HasFile プロパティというのがある。これで、ファイルを指定せずに「更新」ボタンを押したときの判定が出来る。FileBytes プロパティで、アップロードされたファイルのバイト配列が取得できる。このバイト配列を元にメモリ ストリームを作り、メモリ ストリームから Bitmap オブジェクトを作成、そのオブジェクトの Save メソッドで、ファイルに保存してやればいいだろう。と、大まかに流れを組み立てる。

では、「画像ファイル」として、「画像ではないファイル」を指定されたらどうするか。Bitmap クラスのコンストラクタを見ると、ArgumentException 例外を発生させるらしい。とりあえず、これだけを受けて、検査例外に読み替えてやればいいだろう。

ClientBin へのパスは、どうやって取得する?HttpRequest クラスに、Default.aspx への仮想パス名を格納したプロパティがあるはず。そこから MapPath メソッドで物理パス名に変換、System.IO.Path クラスの GetDirectoryName メソッドでパスに変換して、ClientBin を Combine してやればいいだろう。


ってことで、コード。

アップロードされたファイルを保存する
protected void Page_Load(object sender, EventArgs e) {
    Label1.Text = "";
    if (IsPostBack == false) {
        // 初期表示なのでファイルはないはず
        return;
    }
    if (this.FileUpload1.HasFile == false) {
        // ファイルが添付されていないので、以下の処理は必要なし
        return;
    }
    try {
        SaveBitmapFile();
    } catch (ArgumentException) {
        // 指定されたファイルが画像ではないと思われる。
        // 例外は握りつぶす。
        Label1.Text = "指定されたファイルは、画像ではないようです。画像を指定してください。";
    }
}
private void SaveBitmapFile() {
    // アップロードされたファイルをメモリ ストリームに取り込む。
    using (MemoryStream memStrm = new MemoryStream(this.FileUpload1.FileBytes, false)) {
        // メモリ ストリームから、ビットマップに変換する。
        using (Bitmap map = new Bitmap(memStrm)) {
            // App_Data へ、
            string saveFile = System.IO.Path.Combine(
                System.IO.Path.GetDirectoryName(
                this.MapPath(this.Request.FilePath)), @"ClientBin\MapData.png");
            // PNG 形式で保存する。
            map.Save(saveFile, System.Drawing.Imaging.ImageFormat.Png);
        }
    }
}

次、Silverlight の方。

なんも無し。Grid の中に Image を置くだけ。

Page.xaml
<Image x:Name="imgBackground" Stretch="Uniform" Source="MapData.png" />

え?「置いたイメージの大小によって、Image オブジェクトのサイズを変えろ」ですって?

余力があれば、チャレンジします。。。

おっと、最初に実行する前に、何でもいいので MapData.png って名前の画像ファイルを置いておいてくださいね。でないと、実行時にエラーになりますから。

投稿日時 : 2008年12月9日 22:58
コメント
タイトル
名前
Url
コメント