(download sample source code)
今度はミニマムなフォームを作ってみましょう。
<UserControl xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="JSSample4"> <StackPanel> <TextBlock x:Name="label_top" Text="What's your name?" /> <TextBox x:Name="text_name" /> <Button x:Name="cmd_submit" x:Content="submit" /> </StackPanel> </UserControl>
と書いてみますが、これはそのままだとchironでは動いてくれません。
Silverlight2で利用可能なコントロールにはcore APIとlibrary API群に分けられており、純粋にコアとなるのSilverlightランタイムには最小限のコントロールしか用意されていません。
このため、たとえボタンのように一見標準コントロールのように見えてもlibraryに追い出されているコントロールがあるのです。
Visual Studioを使用したCLRアプリであれば、参照設定などもできるのですが、現時点で私が見つけているchironから利用可能な方法はもう少し回りくどい方法になります。
これを解決するためにappフォルダに新しい定義ファイル
app\AppManifest.xaml
を追加します。
<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" RuntimeVersion="2.0.30226.00" EntryPointAssembly="Microsoft.Scripting.Silverlight" EntryPointType="Microsoft.Scripting.Silverlight.DynamicApplication"> <Deployment.Parts> <!-- Core DLR and DLR <-> Silverlight shim assemblies --> <AssemblyPart Name="Microsoft.Scripting.Silverlight" Source="Microsoft.Scripting.Silverlight.dll" /> <AssemblyPart Source="Microsoft.Scripting.dll" /> <!-- Language assemblies --> <AssemblyPart Source="Microsoft.JScript.Compiler.dll" /> <AssemblyPart Source="Microsoft.JScript.Runtime.dll" /> <!-- Silverlight SDK controls assemblies --> <AssemblyPart Name="System.Windows.Controls" Source="System.Windows.Controls.dll" /> </Deployment.Parts> </Deployment>
これで、まずはOk。
そして、フォームのイベントハンドラをapp.jsに追加します。
Import("System.Windows.Application") Import("System.Windows.Controls.UserControl") function sample_app() { this.scene = Application.Current.LoadRootVisual(new UserControl(), "app.xaml"); } sample_app.prototype = { start:function() { this.scene.cmd_submit.Click += function(s,e){ s.Parent.label_top.Text = "Welcome "; } this.scene.cmd_submit.Click += function(s,e){ s.Parent.label_top.Text += s.Parent.text_name.Text + "!"; } } } app = new sample_app; app.start();
これでフォームのボタンが動作したと思います。
このコード、JSの使い手の方なら、ボタンのイベントハンドラの追加部分に違和感を感じると思います。
一般のJSであれば、Clickイベントに=でfunctionを代入するところですが、SilverlightのManaged Javascriptでは += でdelegate(デリゲート)を使用します。C#や.NETの特徴の話でよく出てくる奴ですね。this.scene.cmd_submit.Click += function(s,e){ s.Parent.label_top.Text = "Welcome "; } this.scene.cmd_submit.Click += function(s,e){ s.Parent.label_top.Text += s.Parent.text_name.Text + "!";
}
これにより、このサンプルのように、特に意識する必要なく、複数のイベントハンドラを一つのイベントに割り当てることができます(厳密に言うと、この場合マルチキャスト デリゲートかな)。functionはイベントに追加された順に呼び出されます。 delegateを使用することで、元のイベントハンドラをローカル変数に保存してイベントチェーンを...、などという手間が必要なくなるわけです。delegateの詳細に関しては別途いろいろ調べてみてください。
Silverlightコントロールのxap化と配置:
次に、コマンドラインオプションを変更してchironを起動してみましょう。
chiron /z:app.xap
これで、プロジェクトルートのindex.htmlの隣にapp.xapファイルが作成されたと思います。
このapp.xapファイルと、最初に作成したプロジェクトルートのindex.htmlをサーバーに登録すれば、Silverlightの配置は完了です。
(サーバーに.xapのMIMEタイプ(application/x-silverlight-app)の登録も必要)
xapファイルはイメージ的にはFlashのswfファイルに近いSilverlightアプレットファイルですが、JSのコードがコンパイルされてバイナリになっているわけではありません。
試しに、app.xapのファイル名をapp.xap.zipへリネームしてみれば、zip形式のアーカイブになっているのが確認できると思います。
Office2007のOffice Open XML形式(docxとかxlsxとか)と同じ、最近のMicrosoftのお得意の手口ですね。
また、このアーカイブにはこのアプリから参照設定されている各種DLLが含まれているのも確認できると思います。
これを踏まえた上で、AppManifest.xaml内の
に注目してください。EntryPointAssembly="Microsoft.Scripting.Silverlight" EntryPointType="Microsoft.Scripting.Silverlight.DynamicApplication"
CLRによる.NETコンポーネントに対応したSilverlight2では、DLRアプリの場合もCLRコンポーネントであるMicrosoft.Scripting.Silverlightがエントリーポイントとして呼び出され、これがDLRとしてLLにより書かれたコードをダイナミックにロードしていく形になります。
クライアントにインストールされたSilverlightランタイムが直接JSを実行しているわけではなく、xap内に収められたMicrosoft.Scripting.Silverlight.dllを呼び出しているため、これによって、コントロールを追加する、など、Silverlight自体の機能をダイナミックに拡張できる構造となっているようです。
この点を頭に入れておくと、モジュールのロードプロセスの理解やdebugの際のイメージに役立つでしょう。