次の方法で共有


動的な .NET

Silverlight と IronRuby を使用して対話型の Bing Maps を作成する

Ashish Ghoda

Silverlight の注目すべき機能の 1 つは、IronRuby や IronPython といった動的言語のサポートです。この統合機能により、Silverlight プラットフォーム (プレゼンテーション層用の XAML や分離コード用の動的言語) を使用したリッチ インターネット アプリケーション (RIA: Rich Internet Application) の開発が可能になります。今回の記事では、動的言語と Microsoft Bing Maps コントロールを使って、Silverlight のこの統合機能について説明します。最初に、動的言語について簡単に説明してから、Silverlight による動的言語へのサポートについて説明します。その際、Silverlight の Microsoft Bing Maps コントロールと IronRuby を使用して、3D アニメーションで場所を検索する対話型の Silverlight アプリケーションを構築する方法を示します。

動的言語の基礎

Read-Eval-Print Loop (REPL) 環境では、動的プログラミング言語 (実行時に動的に型指定してコンパイルする言語) を使用することによって、軽量で "即時性のある" プログラミング機能が開発者に提供されます。特定のデータ型の変数を宣言する必要はありません。ランタイムが式のコンテキストに応じてすべて処理します。

よく使用される C# や Visual Basic などの言語は、基本的に厳密性が高く、静的に型指定する言語です。動的言語による開発や配置は、コンパイルと出力結果の配布が必要になるこれらの静的言語に比べれば、より簡単になります。ただし、動的に型指定される言語を使用する場合は、タイプ セーフ性の検証とテストを適切に行う必要があります。

動的言語では、関数を作成し、その関数を変数に代入したり、別の関数にパラメーターとして渡したりできます。そのため、クロージャのような関数や、関数をパラメーターとして渡す処理がはるかに容易です。一般に、クロージャの 2 つの明確な特徴は、コード ブロック (関数) を変数に代入する機能と、このコード ブロックが作成されたときにアクセス可能だった変数に、このコード ブロックからアクセスし続けることができるようにする機能です。

次に示すこれまで使い慣れた C# の ShortWords メソッドは、最大文字数が 3 文字以下という条件に一致する単語を一覧するサブセットを返します。

public static List<string> ShortWords(List<string> wordList) {
  List<string> shortWordList = new List<string>();
  int maximumWordLength = 3;
  foreach(string word in wordList) {
    if(word.Length <= maximumWordLength) {
      shortWordList.Add(word);
    }
  }
  return(shortWordList);
}

LINQ では、次のコード スニペットに示すように、同じ機能をはるかに効率的に実現できます。

public static List<string> ShortWords(List<string> wordList) {
  var maximumWordLength = 3;
  return wordList.Where(w => w.Length <=      
     maximumWordLength).ToList<string>();
end

IronRuby (プログラミング言語 Ruby の Microsoft .NET Framework 向け実装) などの動的言語で同じメソッドを実装すると、LINQ 方式を C# で採用するのと同様に、従来の手法に比べてコードが大幅に短くなります。

def ShortWords(wordList)
  maximumWordLength = 3
  return wordList.select {|w| w.Length <= maximumWordLength}
end

同じアルゴリズムを備えるこれら 2 つの実装を比較すると、IronRuby (および動的言語一般) に関して多くのことが明らかになります。IronRuby コードは簡潔で、string や int といったデータ型キーワードが見当たりません。

この IronRuby コード ブロックで最も興味深い点は、中かっこで囲んだクロージャです。ここでは、事実上関数であるクロージャを、select メソッドに渡しています。select メソッドは、クロージャを使用して、コレクションのサブセットを抽出します。クロージャを形成しているコードは、実際には select メソッド内で実行されます (ここでは、クロージャは、wordList コレクション内で条件を満たしている文字列を抽出しています)。しかし、元のスコープにある変数 (この場合は、maximumWordLength 変数) にもアクセスし続けることができています。

クロージャは、この単純な例で示すよりもはるかに強力です。C# で LINQ を使用したり、デリゲートを Exists や Find などのメソッドに渡したりすることに似ていますが、元のスコープへのアクセスを保持するというメリットが追加されます。クロージャの詳細については、私が Jeff Scanlon と共同で執筆した『Accelerated Silverlight 3』 (Apress、2009 年 7 月) をご覧ください。

Silverlight 向けの動的言語

Silverlight は、現状、マイクロソフトの動的言語ランタイム (DLR) エンジンを通じて動的言語の IronRuby と IronPython をサポートしています。このエンジンは、Microsoft .NET Framework の共通言語ランタイム (CLR) 上で実行される動的言語用汎用プラットフォームおよびホスティング モデルです。

DLR は、動的言語で記述されたコードを .NET プラットフォームで実行できるように、リフレクションを使用して実行時に型を動的に検出する、.NET Framework のライブラリとサービスのセットです。

次に示す 5 つの DLR スクリプト アセンブリは、ランタイム スクリプト環境を提供し、動的言語と Silverlight の橋渡しをします。

  • Microsoft.Scripting.dll
  • Microsoft.Scripting.Core.dll
  • Microsoft.Scripting.Silverlight.dll
  • Microsoft.Scripting.ExtensionAttribute.dll
  • Microsoft.Scripting.Debugging.dll

Microsoft.Scripting.Silverlight.dll には、開発者が動的言語を使用して Silverlight アプリケーションを記述することができるクラスが含まれています。重要なクラスの 1 つに、System.Windows.Application から直接継承する DynamicApplication クラスがあります。このクラスは、動的言語のコードから表示要素にアクセスできるようにすることによって、Silverlight ベースの動的なアプリケーション オブジェクトを表現し、Silverlight のホスト上で動的言語アプリケーションをホストするためのエントリ ポイントになります。また、Application クラスに既に用意されている Host、Resources、および RootVisual の各プロパティを拡張する、追加のプロパティを提供します。

IronRuby (ironruby.net、英語) は、プログラミング言語 Ruby のオープン ソース実装で、Ruby と .NET Framework 間の統合を提供します。

現バージョンの IronRuby (1.0 RC1) では、.NET Framework 3.5 と .NET Framework 4 のベータ版がサポートされます。IronRuby 1.0 RC1 は、.zip と .msi の両方のダウンロードが提供されています。Silverlight アプリケーションでは、.zip バージョンを使用することをお勧めします。

IronPython (ironpython.codeplex.com、英語) は、プログラミング言語 Python のオープン ソース実装で、IronRuby と同様、Python 言語と .NET Framework の統合を可能にします。現時点では、.NET Framework 3.5 および .NET Framework 4 のベータ版用の IronPython 2.6 をダウンロードできます。

IronRuby と IronPython には、特定の言語をサポートする 2 つのアセンブリが存在しており、言語を解析してホスト環境と通信するといった機能が提供されます。IronPython には IronPython.dll と IronPython.Modules.dll が、IronRuby には IronRuby.dll と IronRuby.Libraries.dll があります。

IronRuby と IronPython はいずれも開発途上にあります。それぞれのホーム ページにアクセスして、最新リリースとドキュメントを確認してください。dlr.codeplex.com (英語) にアクセスして、DLR のソース コードを関連ソース コードと共に入手することもできます。

開発コンポーネントをインストールする

動的言語ベースの Silverlight アプリケーションを開発する手法は 2 種類あります。

  • Chrion.exe という開発ユーティリティを使用する従来の手法
  • インラインのブラウザー スクリプトを使用するテキストのみの手法

この記事では、この両方の手法を簡単に説明し、新しいテキストのみの手法を使用して Microsoft Bing Maps のサンプル アプリケーションを作成します。

Silverlight 2 を導入して以来、マイクロソフトは、DLR のスクリプト ライブラリと共に、Chiron.exe 開発ユーティリティと IronRuby および IronPython の Silverlight アプリケーション プロジェクト テンプレートを通じて、動的言語ベースの Silverlight アプリケーション開発環境を提供してきました。

まず手始めに、DLR と、IronRuby または IronPython のいずれかを前述のサイトからダウンロードしてインストールします。IronRuby および IronPython と共に、サンプル、ドキュメント、ユーティリティ、およびいくつか追加の重要なコンポーネントがインストールされます。

動的言語向けの Silverlight テンプレートでは、コア アプリケーション ファイルが提供されます。これは、Silverlight\script\templates\ruby フォルダーおよび Silverlight\script\templates\python フォルダーにインストールされています。図 1 に、これらのアプリケーション テンプレート ファイルの詳細をいくつか示します。

図 1 動的言語ベースの Silverlight アプリケーション用コア ファイル

IronRuby IronPython と IronRuby を同時にインストール IronPython を個別にインストール 説明
index.html index.html index.html 動的言語ベースの Silverlight アプリケーションのホスト
app\app.rb app\app.py python\app.py Silverlight アプリケーションのメイン スタートアップ ファイル
app\app.xaml app\app.xaml python\app.xaml メイン XAML ユーザー インターフェイス ファイル
css\screen.css css\screen.css stylesheets\screen.cs アプリケーションのスタイル定義
なし なし stylesheets\error.css アプリケーション エラーのスタイルと書式の定義
js\error.js js\error.js javascripts\error.js ハンドルされないアプリケーション エラーを管理

Script フォルダーには、sl.bat ファイルが含まれています。これは、動的言語ベースの Silverlight アプリケーションの暫定版を作成するのに役立ちます。次のコードは、このバッチのコマンド ライン形式を示しています。

sl [ruby|python] <ApplicationPath>

Chiron.exe (Silverlight 開発ユーティリティ) は、一連のファイルを配置用の .xap ファイルに動的にパッケージ化します (Chiron.exe とコンパイルの詳細については、blog.jimmy.schementi.com/2009/03/state-of-dlr-for-silverlight.html (英語) を参照してください)。

Chiron.exe と /b (ブラウザー) オプションを使用してアプリケーションを起動できます。

Chiron /b

Chiron.exe の興味深い機能の 1 つは、アプリケーション ディレクトリ内でファイルを変更すると、Chiron.exe がアプリケーションを .xap ファイルにパッケージ化し直してから再読み込みすることです。ただし、すべてのアクティブなブラウザー セッションを最新情報に更新する手順は依然として必要です。

テキストのみの手法

従来の DLR ベースの開発手法では、Chrion.exe ユーティリティの使用が必須で、編集してコンパイルしてから最新状態に更新するという従来の開発モデルに従います。

現在は、ブラウザーの HTML (および XHTML) マークアップ内に IronRuby、IronPython、および XAML コードを直接記述できるようになりました (詳細については、ironruby.com/browser (英語) を参照してください)。これは、テキストのみの手法と呼ばれます。DLR ベースのアプリケーションを作成および実行するためになんらかのコンポーネントをインストールする必要はありません。テキストのみの手法では、書き込んで保存してから最新の状態に更新するという開発モデルに従うため、Chrion.exe を使用する必要はありません。

テキストのみの手法を使用すると、前述の IronRuby および IronPython の言語固有のアセンブリだけでなく、DLR スクリプト アセンブリのローカル コピーすら必要ありません。Gestalt というサンプル パッケージ (ironruby.com/browser (英語) から入手できます) にはバイナリが含まれていますが、既知のサーバーから dlr.js を参照することもできます。その場合は、何もインストールしていないことが前提です。ただし、Silverlight コントロールをホストして、HTML ページ内で DLR 統合を有効にするための方法は必要です。

Gestalt プロジェクトでは、既存の Silverlight.js の手法を使用します。つまり、JavaScript API を使用して Silverlight コントロールをホストする Object タグを作成します。また、クライアント コンピューターで、エラーを管理し、ブラウザーおよび Silverlight プラグインの要件を検出することもできます。Mix Online Lab チームは、インライン スクリプトと DLR の統合機能を含めるよう Silvelright.js ファイルを強化して、ファイル名に dlr.js と変更しました。

始めに、Gestalt プロジェクトは、DLR に基づいて構築され、ブラウザーおよびプラットフォームを問わずに使用できるライブラリを提供します。圧縮形式のライブラリ ファイル gestalt.zip は、visitmix.com/labs/gestalt/downloads (英語) から入手できます。図 2 に、この .zip ファイルに含まれるコア ファイルの詳細を示します。

図 2 テキストのみの手法のコア ライブラリ ファイル

IronRuby ファイル 説明
dlr\dlr.js 動的言語ベースの Silverlight アプリケーションをホストし、HTML ページでインライン スクリプトを有効にするために強化された Silverlight.js ファイル
dlr\ gestaltmedia.js HTML5 のビデオおよびオーディオの再生を有効にする
dlr\dlr.xap Microsoft.Scripting.slvx を参照し、Microsoft.Scripting.Silverlight.dll をエントリ ポイント アセンブリとして指す AppManifest.xaml ファイル、および DLR 言語の構成情報提供する languages.config を含む
dlr\IronRuby.slvx IronRuby ベースの Silverlight アプリケーションを開発できる、IronRuby.dll ファイルと IronRuby.Libraries.dll ファイルを含む
dlr\IronPython.slvx IronPython ベースの Silverlight アプリケーションを開発できる、IronPython.dll ファイルと IronPython.Modules.dll ファイルを含む
dlr\ Microsoft.Scripting.slvx ランタイムにスクリプト環境を提供し、動的言語と Silverlight の橋渡しをする、5 つの DLR スクリプト アセンブリ (Microsoft.Scripting.dll、Microsoft.Scripting.Core.dll、Microsoft.Scripting.Silverlight.dll、Microsoft.Scripting.ExtensionAttribute.dll、および 
Microsoft.Scripting.Debugging.dll) を含む
samples\getting.started\*.html インライン スクリプト、IronRuby、IronPython、および XAML の機能を示すサンプル Web ページ

Silverlight 3 から、開発者は Transparent Silverlight Extensions (透過的な Silverlight 拡張) の機能を使用して、よく使用されるアセンブリ ファイルを、.slvx ファイル名拡張子が付いた、独立した再利用可能ライブラリとしてパッケージ化できるようになりました。.slvx ファイルは、インターネット上の共通の場所やクライアント固有の場所に配置できます。必要な .slvx ファイルは、正しいパスを使用して、ExternalParts セクション内の AppManifest.xaml ファイルで、ExtensionPart として参照される必要があります。

Jimmy Schementi が執筆した、テキストのみの手法に関する優れたドキュメント (ironruby.com/browser/sl-back-to-just-text.pdf、英語) では、非常に有用なガイダンスが提供されています。また、dlr.js ファイルの既定の DLR 設定を変更する方法についても詳しく説明しています。

DLR ベースのインライン スクリプトを含む Web アプリケーションをホストして実行するには、IIS や Apache などの Web サーバー インスタンスが必要です。gestalt.zip から、Dlr フォルダーと Samples フォルダーを、Web サーバーのルートに配置します。これらのフォルダーを Web サーバーのルートにインストールしない場合は、dlr.js ファイルを適切に変更する必要があります。

次に、以下のようにして、.rb、.py、および .slvx の各ファイルに MIME の種類を追加します。

  • .rb ファイルと .py ファイルでは、MIME の種類を text/plain に設定します。
  • .slvx ファイルでは、MIME の種類を application/octet-stream に設定します。

環境を検証するには、samples\get.started フォルダーに移動して、05_final.html ファイルを参照します。この Web ページは、アニメーションの統合機能を使って、IronPython、HTML、および XAML ベースのグラフィックスの例を示します (図 3 参照)。

image: Running the Gestalt Project’s Sample Application

図 3 Gestalt プロジェクトのサンプル アプリケーションの実行

Silverlight、IronRuby、およびテキストのみの手法

まず、IronRuby を使用して DLR ベースの Silverlight アプリケーションの骨組みを定義し、テキストのみの手法に従います。Gestalt の複数のファイルを Web サーバーのルートにコピーしたら、テキスト エディターを開いて HTML ファイルの記述を開始します。とても簡単ですね。

この方法がすばらしい点は、dlr.js によって Silverlight コントロールがページに追加され、動的言語の統合機能を有効にするために必要なすべての主要要件が提供されるところです。このため、dlr.js ファイルを HTML ページに追加するだけでかまいません。

<head>
  <script src="/dlr/dlr.js" type="text/javascript"></script> 
</head>

dlr.js を追加すると、DLR ベースの Silverlight アプリケーションの既定の設定が構成されます。この設定をカスタマイズする場合は、HTML ファイル内でカスタム スクリプト コードを記述することによって、既定の設定を上書きする必要があります。詳細については、先ほど紹介した Jimmy Schementi のドキュメントを参照してください。

これで、HTML ファイルの script タグ内に、XAML コード と IronRuby コードまたは IronPython コードを記述するための準備が整いました。インラインの IronRuby コードを記述するには、次のように、script タグに適切な型とクラスの情報を追加し、このタグ内に IronRuby コードを配置する必要があります。

<script type="application/ruby" 
  class="Class Name Goes Here"> 
  IronRuby Code Goes Here
</script>

インラインの IronPython コードを記述するには、IronRuby コードの場合と同じ手順を、該当する部分を IronPython に置き換えて実行します。

<script type="application/python" 
  class="Class Name Goes Here"> 
  IronPython Code Goes Here
</script>

インラインの XAML コードを記述するには、script タグに適切な型、ID、幅、および高さの情報を追加して、このタグ内に XAML コードを配置します。

<script type="application/xml+xaml" id="Place ID here" 
  Width="400" Height="400"> 
  <UserControl ...>
    XAML Code Goes Here
  </UserControl>
</script>

XAML コントロールにアクセスし、コードを使用してイベントの統合を実装できます。これについては、次のセクションでアプリケーションを開発しながら説明します。コードの記述が完了して、ページに移動すると、アプリケーションの結果がすぐに表示されます。

Bing Maps の統合

インライン スクリプトによるテキストのみの手法を使用して、動的言語ベースの Silverlight アプリケーションの基本的な骨組みを確認したので、さらに一歩進めて、Microsoft Bing Maps (旧称 Virtual Earth) と統合してみましょう。

2009 年 11 月に、Microsoft Bing Maps Silverlight Control SDK のバージョン 1 がリリースされました (msdn.microsoft.com/library/ee681884、英語)。このインストーラーは、BingMapsSilverlightControlv1.0.1Installer.msi です。このコントロールを使用するには、少なくとも Silverlight 3 が必要です。インストールには、Microsoft.Maps.MapControl.dll と Microsoft.Maps.MapControl.xml、Microsoft.Maps.MapControl.Common.dll と Microsoft.Maps.MapControl.Common.xml、およびオフライン ドキュメントが含まれます。

Silverlight Bing Maps コントロールを使用してアプリケーションのビルドを開始する前に、Bing Maps 開発者アカウントを作成して、アプリケーションの認証キーを入手します。これを行うには、bingmapsportal.com (英語) にアクセスします。

SDK バージョン 1 のリリース以前は、Microsoft Bing Maps Silverlight コントロールの CTP リリースを入手できました。CTP リリースと比較すると、バージョン 1 には重要な変更と機能拡張が加えられています。CTP リリースとバージョン 1 リリースの主な違いを理解するには、msdn.microsoft.com/library/ee681889 (英語) を参照してください。

ここで、SilverlightMap.html ファイルを作成し、前述のように dlr.js ファイルを追加します。

AppManifest.xaml ファイル (dlr.xap ファイルに含まれています) を変更し、Microsoft.Maps.MapControl.dll ファイルと 
Microsoft.Maps.MapControl.Common.dll ファイルを追加して、アプリケーション起動の一環として読み込みます。これを行うには、dlr.xap の名前を dlr.xap.zip に変更し、このファイルから AppManifest.xaml ファイルと languages.config ファイルを抽出します。その後、Microsoft.Maps.MapControl.dll ファイルと Microsoft.Maps.MapControl.Common.dll ファイルを AssemblyPart として追加します (図 4 参照)。

図 4 変更後の AppManifest.xaml ファイル

<Deployment
  xmlns="https://schemas.microsoft.com/client/2007/deployment"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  RuntimeVersion="2.0.31005.0"
  EntryPointAssembly="Microsoft.Scripting.Silverlight"
  EntryPointType="Microsoft.Scripting.Silverlight.DynamicApplication"
  ExternalCallersFromCrossDomain="ScriptableOnly">
  <Deployment.Parts>
    <AssemblyPart Source="Microsoft.Maps.MapControl.dll" />
    <AssemblyPart Source="Microsoft.Maps.MapControl.Common.dll" />
  </Deployment.Parts>
  <Deployment.ExternalParts>
    <ExtensionPart Source="Microsoft.Scripting.slvx" />
  </Deployment.ExternalParts>
</Deployment>

ここで、変更した AppManifest.xaml、既存の langugages.config、Microsoft.Maps.MapControl.dll、および Microsoft.Maps.MapControl.Common.dll の各ファイルを zip ファイルに圧縮してから、この .zip ファイルの名前を dlr.xap に変更します。この新しいファイルを、Web サーバーの (Dlr フォルダーの下にある) 既存の dlr.xap ファイルに上書きします。

次に、SilverlightMap.html ファイルを開き、XAML コード用に script タグを追加してから、Silverlight_map という UserControl と、必要な名前空間を作成するためのマップ コントロールへの参照を追加します (図 5 参照)。

図 5 HTML ファイルでのマップ コントロールへの参照

<Deployment 
  xmlns="https://schemas.microsoft.com/client/2007/deployment" 
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  RuntimeVersion="2.0.31005.0" 
  EntryPointAssembly="Microsoft.Scripting.Silverlight" 
  EntryPointType="Microsoft.Scripting.Silverlight.DynamicApplication"
  ExternalCallersFromCrossDomain="ScriptableOnly">
  <Deployment.Parts>
    <AssemblyPart Source="Microsoft.Maps.MapControl.dll" />
    <AssemblyPart Source="Microsoft.Maps.MapControl.Common.dll" />
  </Deployment.Parts>
  <Deployment.ExternalParts>
    <ExtensionPart Source="Microsoft.Scripting.slvx" />
  </Deployment.ExternalParts>
</Deployment>
<script type="application/xml+xaml" id="sl_map" 
  Width="1350" Height="575">
  <UserControl x:Name="silverlight_map" 
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" Width="200" 
    Height="280" Background="Black" 
    xmlns:d="https://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" 
    xmlns:m="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl">
</UserControl>
</script>

最後に、Canvas コントロールをメイン コンテナーとして追加し、Grid コントロールの下に Map 要素を追加します。Canvas コントロールと Grid コントロールの幅と高さが同じに保たれ、Map コントロールの Width プロパティと Height プロパティが、それぞれ 800 と 400 に設定されていることがわかります。

<Canvas x:Name="container" Width="1350" Height="575">
<Grid x:Name="layout_root" Width="1350" Height="575">    
<m:Map CredentialsProvider="AuthenticationKey" 
  Width="800" Height="400" Grid.Column="1" 
  HorizontalAlignment="Center"/>
</Grid>
</Canvas>
</UserControl>

このコード スニペットの "AuthenticationKey" は、Map コントロールの認証キーに置き換える必要があります。

このファイルを、Web サーバーにある既存の Sample\Getting.started フォルダーにコピーして、このページを参照します。既定の道路地図モードで地図が表示されます (図 6 参照)。

image: DLR-Based Bing Map Silverlight Application in Default Road Map Mode

図 6 既定の道路地図モードの DLR ベースの Bing Maps Silverlight アプリケーション

地図のモードと 3D アニメーション

地図のモードを地名表示付き航空写真に変更し、既定のビューとして設定しましょう。また、地図に 3D アニメーションを導入します。

地図の既定のモードを変更するには、まず、Map 要素に名前を付けて (この例では、map_in_ironruby)、IronRuby ベースのインライン コードから参照できるようにします。また、Map オブジェクトに 3D 投影を適用します。これは、Silverlight 3 の新機能です。これを行うために、Map オブジェクトの Projection プロパティを PlanProjection に設定し、RotationX プロパティを -20 に設定します。これにより、Map オブジェクトが変形し、視点がやや傾斜します。

<Grid x:Name="layout_root" Width="1350" Height="575" Background="Black">    
  <m:Map x:Name="map_in_ironruby" 
  CredentialsProvider="AuthenticationKey" 
  Width="800" Height="400">
    <m:Map.Projection>
      <PlaneProjection RotationX="-20"/>
    </m:Map.Projection>   
  </m:Map>
</Grid>

また、Grid の背景を黒に変更しました。

次に、IronRuby 用に script タグを追加し、次のコード行を記述して、必要なアセンブリ (MapControl.dll を含む) を追加します。その後、Map コントロールで地名表示付き航空写真ビューを有効にします。

新しいテキストのみの手法では、Map オブジェクトを名前で参照できます。現バージョンの Gestalt のライブラリでは、me や xaml といった短縮形を使用してオブジェクトを参照する必要があります (ここでは、me を使用しました)。将来的には、root_visual の短縮形によって、x:Name を使って XAML 要素にアクセスできるようになります。

<script type="application/ruby" class="sl_map">
  require "Microsoft.Maps.MapControl.dll"
  require "Microsoft.Maps.MapControl.Common.dll"
  include System::Windows
  include System::Windows::Controls
  include Microsoft::Maps::MapControl
  sm = me.silverlight_map
  sm.map_in_ironruby.mode = AerialMode.new(true) 
</script>

IronRuby 関連の script タグのクラス名は sl_map のままにしました。これは、XAML 関連の script タグの ID と同様です。

ここでアプリケーションを実行すると、黒の背景、傾斜した 3D の角度、および地名表示付き航空写真ビューが表示されます (図 7 参照)。

image: Map Mode Set to Aerial with Labels Mode and with 3-D Projection

図 7 地名表示付き航空写真モードと 3D 投影を設定した地図モード

MIX09 カンファレンスで好評だったデモンストレーションの 1 つが、Map オブジェクトの回転機能を備えた Silverlight と Microsoft Bing Maps の統合でした。IronRuby で同様の機能を実装してみましょう。

この機能を実装するには、まず、ColumnDefinitions を使用して、2 つの列を含む Grid を定義する必要があります。

<Grid.ColumnDefinitions>
  <ColumnDefinition Width="200"/>
  <ColumnDefinition Width="1100"/>
</Grid.ColumnDefinitions>

次に、Rotate Map、Pause、Stop and Reset という名前が付いた 3 つのボタンを追加し、XAML ファイルの Border 要素内にタイトル テキストを追加します。これらはすべて、Grid の 1 つ目の列に配置します (図 8 参照)。

図 8 Grid オブジェクトへのコントロールの追加

<StackPanel Grid.Column="0" Orientation="Vertical">
  <Border CornerRadius="20" Margin="0,50,0,5" Width="150" 
    Background="DarkBlue" HorizontalAlignment="Center">
    <StackPanel Orientation="Vertical">
      <TextBlock Text="3D Rotation"
        HorizontalAlignment="Center"
        FontSize="12" Foreground="White" Margin="0,5,0,10"/>
      <Button x:Name="RotateMap" Height="25"
        Content="rotate_map" Width="100" Margin="0,0,0,10"
        Foreground="Black" VerticalAlignment="Center"
        HorizontalAlignment="Center" />
      <Button x:Name="pause_resume" Height="25"
        Content="Pause" Background="DarkGoldenrod"
        Foreground="Black" Width="100" Margin="0,0,0,10"
        VerticalAlignment="Center"
        HorizontalAlignment="Center" />
      <Button x:Name="stop_reset" Height="25"
        Content="Stop and Reset" Background="DarkGoldenrod"
        Foreground="Black" Width="100" Margin="0,0,0,10"
         VerticalAlignment="Center"
         HorizontalAlignment="Center" />
    </StackPanel>
  </Border>
</StackPanel>

ここで、Map オブジェクトを Grid の 2 つ目の列に追加します。

<m:Map x:Name="map_in_ironruby" 
  CredentialsProvider="AuthenticationKey" 
  Width="800" Height="400" Grid.Column="1" 
  HorizontalAlignment="Center">
  <m:Map.Projection>
    <PlaneProjection RotationX="-20" RotationY="0" 
      RotationZ="0"/>
  </m:Map.Projection>
</m:Map>

次の手順では、やや複雑な XAML 更新コードを作成する必要があります。Visual Studio や Expression Blend などの開発環境を使用して XAML ファイルを作成し、これらの環境の編集機能や IntelliSense 機能を活用することをお勧めします。その後、完成した XAML を、プロジェクトの app.xaml ファイルにコピーできます。

map_in_ironruby という名前の Map オブジェクトを対象とする、map_animation という名前の Storyboard を作成します (このコードの抜粋については、図 9 を参照してください。Storyboard コード ブロック全体については、この記事のコード ダウンロードを参照してください)。Storyboard では、PlaneProjection アニメーション プロパティの RotationZ、RotationY、GlobalOffsetX、および GlobalOffsetZ のキーフレームを定義します。StoryBoard を UserControl リソースとして追加します。

図 9 アニメーションの Storyboard の作成

<StackPanel Grid.Column="0" Orientation="Vertical">
  <Border CornerRadius="20" Margin="0,50,0,5" Width="150" 
    Background="DarkBlue" HorizontalAlignment="Center">
    <StackPanel Orientation="Vertical">
      <TextBlock Text="3D Rotation" 
        HorizontalAlignment="Center" 
        FontSize="12" Foreground="White" Margin="0,5,0,10"/>
      <Button x:Name="RotateMap" Height="25"
        Content="rotate_map" Width="100" Margin="0,0,0,10" 
        Foreground="Black" VerticalAlignment="Center" 
        HorizontalAlignment="Center" />
      <Button x:Name="pause_resume" Height="25" 
        Content="Pause" Background="DarkGoldenrod" 
        Foreground="Black" Width="100" Margin="0,0,0,10" 
        VerticalAlignment="Center" 
        HorizontalAlignment="Center" />
      <Button x:Name="stop_reset" Height="25" 
        Content="Stop and Reset" Background="DarkGoldenrod" 
        Foreground="Black" Width="100" Margin="0,0,0,10" 
        VerticalAlignment="Center" 
        HorizontalAlignment="Center" />
    </StackPanel>
  </Border>
</StackPanel>
<UserControl.Resources>
  <Storyboard x:Name="map_animation">
    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" 
      Storyboard.TargetName="map_in_ironruby" 
      Storyboard.TargetProperty=
        "(UIElement.Projection).(PlaneProjection.RotationZ)">
      <EasingDoubleKeyFrame KeyTime="00:00:00" Value="15"/>
      <EasingDoubleKeyFrame KeyTime="00:00:01" Value="0"/>
      <EasingDoubleKeyFrame KeyTime="00:00:02" Value="-15"/>
      <EasingDoubleKeyFrame KeyTime="00:00:03" Value="0"/>
      <EasingDoubleKeyFrame KeyTime="00:00:04" Value="15"/>
    </DoubleAnimationUsingKeyFrames>
    ...
  </Storyboard>
</UserControl.Resources>

次に、インラインの IronRuby コードに Click イベントを追加して、アニメーションを開始、一時停止、再開、および停止します。まず、System.Windows.Media および System.Windows.Media.Animation への参照を追加する必要があります。

include System::Windows::Media
include System::Windows::Media::Animation

アプリケーションの初期化プロセス中は pause_resume ボタンを無効にします。

sm.pause_resume.is_enabled = false

ここで、各ボタンの Click イベントを実装します。rotate_map ボタンから説明します。まず、アニメーションで使用可能なスペースを最大限に利用できるように、Map オブジェクトの左側側面を揃えます。次に、StoryBoard アニメーションの RepeatBehavior プロパティを Forever に設定して、アニメーションを開始します。最後に、pause_resume ボタンを有効にして、ボタンのコンテンツを Pause に設定します。

sm.rotate_map.click do |s,e|
  sm.map_in_ironruby.horizontal_alignment = HorizontalAlignment.Left
  sm.map_animation.repeat_behavior = RepeatBehavior.Forever
  sm.map_animation.begin
  sm.pause_resume.is_enabled = true
  sm.pause_resume.content = "Pause"  
end

続いて、pause_resume ボタンの Click イベントを実装します。ここで、一時停止状態か実行中状態かに応じて、Storyboard アニメーションを再開または一時停止し、ボタンのコンテンツを変更します。

sm.pause_resume.click do |s,e|
  strbtnContent = sm.pause_resume.content.ToString
  if strbtnContent == "Pause" 
    sm.pause_resume.content = "Resume"
    sm.map_animation.pause
  else
    sm.pause_resume.content = "Pause"
    sm.map_animation.resume
  end
end

最後に、stop_reset ボタンの Click イベントを実装します。ここでは、Storyboard アニメーションを停止し、pause_resume ボタンを無効にして、ボタンのコンテンツを Pause にリセットします。また、Map オブジェクトも中央に揃えるように戻します。

sm.stop_reset.click do |s,e|
  sm.map_animation.stop
  sm.pause_resume.is_enabled = false
  sm.pause_resume.content = "Pause"
  sm.map_in_ironruby.horizontal_alignment = HorizontalAlignment.Center   
end

Chiron /b コマンドを使用してプロジェクトをコンパイルして実行すると、アニメーション付きの地図が表示されます。図 10 は、回転する地図を示しています。

image: 3-D Map Animation

図 10 3D 地図のアニメーション

あらかじめ定義した場所を対象にする

ここでは、地図上であらかじめ定義した 3 つの場所 (New York、San Francisco、および Vancouver) を強調表示してみましょう。この処理は、Microsoft Bing Maps Silverlight コントロールの CTP のドキュメントの一部として、C# で示されています。ここでは、IronRuby を使用してこの機能を実装する方法について説明します。

まず、インラインの XAML コードを更新して、画面の左側の新しいセクションに、New York、San Francisco、および Vancouver の各場所に対応する 3 つのボタンを追加します。これらは、前述のボタンとほぼ同じように実装します。1 つ注目すべき変更点は、各 Button 要素に Tag 属性を追加していることです。この Tag 属性は、特定の場所の座標と地図の拡大レベルを定義します。

次のコード スニペットは、New York に対応する Button を追加する XAML コードを示しています。

<Button x:Name="newyork" Height="25"    Width="100"
  Content="New York" Margin="0,0,0,10" Foreground="Black" 
  VerticalAlignment="Center" HorizontalAlignment="Center" 
  Tag="40.7199,-74.0030,0.0000 12.0000"/>

この属性によって、各場所の座標情報が提供されます。ユーザーがボタンをクリックすると、この情報を使用して、地図の対象が再設定されます。場所を検索するボタンの全体的なコードについては、コード ダウンロードを参照してください。

ほとんどのアプリケーションにはタイトルが付いているので、このアプリケーションにも同じようにタイトルを付けます。Grid の 2 番目の列に、"Microsoft Bing Maps Silverlight Control and IronRuby Integration" というタイトルを追加しました。これは、既存の Map 要素を置き換えて、StackPanel の下に TextBlock コントロールを追加することによって行いました。

<StackPanel Grid.Column="1" Orientation="Vertical">
  <TextBlock VerticalAlignment="Top" 
    HorizontalAlignment="Center" FontSize="20" 
    Foreground="Red" Margin="0,5,0,0"
    Text="Microsoft Bing Maps Silverlight Control and IronRuby Integration" />
  <m:Map x:Name="map_in_ironruby" Width="800" Height="400" 
    HorizontalAlignment="Center" Margin="0,50,0,20">
...

これでプレゼンテーション層が完成しました。この時点でアプリケーションを実行すると、新しい Location セクションの下に、さらに 3 つのボタンが表示されていることがわかります。ただし、新しく追加されたボタンをクリックしても、地図は対応する場所には移動しません。移動させるには、各ボタンの Click イベントの分離コードを実装する必要があります。

Click イベントは、前述の 3 つのボタンと同じです。クリックされたボタンの Tag プロパティの値に基づいて、それらの座標と拡大レベルをビューへの指示として渡し、新しい地図のビューを作成します。ここで、Split メソッドを使用して座標と拡大レベルを分割し、Maps コントロールの SetView メソッドを使用して地図のビューを設定します。新しい地図のビューに定義済みの場所が表示されます。

sm.newyork.click    do |s,e|      
  tag_information = s.Tag.split
  location_Converter = LocationConverter.new
  location_info = location_Converter.ConvertFrom(tag_information[0].ToString)
  sm.map_in_ironruby.SetView(location_info, tag_information[1]);
end

プログラムに Microsoft.Maps.MapControl.Design への参照を追加して、新しい地図のビューを作成することも必要です。

include Microsoft::Maps::MapControl::Design

これでアプリケーションは完成です。このように、ビューをカスタマイズして、その他の対象となる場所を追加し、追加機能を実装するのは簡単です。

一歩進めて

この記事を締めくくる前に、(XAML と IronRuby または IronPython によって) インライン スクリプト コードを外部に取り出す方法について簡単に紹介します。

プログラミング モデルをモジュール化するには、まず、完成した SilverlightMap.html ファイルをコピーして、SilverlightMap-ExternalScript.html という名前に変更します。その後、SilverlightMap-ExternalScript.html ファイルからインラインの XAML コードを切り取り、空白の新しいテキスト ファイルに貼り付けて、SilverlightMap.xaml という名前を付けて保存します。次に、SilverlightMap-ExternalScript.html ファイルから IronRuby コードを切り取り、空白の新しいテキスト ファイルに貼り付けて、SilverlightMap.rb ファイルという名前を付けて保存します。

ここで、SilverlightMap-ExternalScript.html ファイルの XAML と IronRuby の script タグに src 属性を付け、外部ファイルにした XAML ファイルと IronRuby ファイルへのパスを定義します。

<html><head>
  <script src="/dlr/dlr.js" type="text/javascript"></script> 
</head>
<body>
  <script type="application/xml+xaml" 
    src="/samples/getting.started/SilverlightMap.xaml" 
    id="sl_map" Width="1350" Height="575">
  </script>
  <script type="application/ruby" 
    src="/samples/getting.started/SilverlightMap.rb" 
    class="sl_map">
  </script>
</body> </html>

最後に、3 つの新しいファイル (SilverlightMap-ExternalScript.html、SilverlightMap.xaml、および SilverlightMap.rb) を、Web サーバーの Sample\Getting.started フォルダーにコピーします。SilverlightMap-ExternalScript.html ファイルを参照すると、先ほどと同じ、場所を検索する機能を持つ回転する地図が表示されます。

(Chiron.exe を使用する) 従来の手法を使用して作成した同様のアプリケーションについては、SilverlightStuff.net (英語) にある私の記事を参照してください。     

Ashish Ghoda は、Technology Opinion LLC の創設者および代表取締役であり、四大会計事務所の共同経営者でもあります。Ghoda には、technologyopinion.com (英語) および SilverlightStuff.net (英語) から連絡できます。askashish@technologyopinion.com (英語のみ) から直接連絡することもできます。

この記事のレビューに協力してくれた技術スタッフの Laurence Maroney と Jimmy Schementi に心より感謝いたします。