スクリプトからオブジェクトを操作する
実行中に、スクリプトからオブジェクトのプロパティを操作することも可能です。Silverlightでは読み込んだXAMLファイルから、オブジェクトが生成され、色やサイズといった基本的なプロパティが初期設定されていますが、実行時にスクリプトからプロパティの値を変更することもできます。JavaScriptからオブジェクトを操作する場合でも、XAMLの属性と同じ名前と値が利用できます。例えば、TextBlockオブジェクトが表示しているテキストを変更したい場合はTextプロパティから新しい文字列を設定します。
value = object.Text object.Text = value
XAMLでTextBlockオブジェクトを初期化する場合は、Text属性から値を設定するか、コンテンツ要素として文字列を指定する方法がありましたが、スクリプトからの変更は、常にプロパティから行います。Textプロパティにアクセスすることで、オブジェクトが現在している文字列を取得したり、別の文字列を設定して表示させることができます。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Silverlight test</title> <script type="text/javascript" src="Silverlight.js"></script> <script type="text/javascript"> var root; function onLoadHandler(sender, context, source) { root = source; } function onClickHandler() { var text = document.getElementById("textInput"); root.Text = text.value; } </script> </head> <body> <div> <input type="text" id="textInput"></input> <input type="button" onclick="onClickHandler()" value="OK"></input> </div> <div id="silverlight"></div> <script type="text/javascript"> var parentElement = document.getElementById("silverlight"); Silverlight.createObject( "test.xaml", //ソースファイル parentElement, //Silverlight を表示するDIVタグのDOMオブジェクト "silverlight01", //任意の一意なプラグインID { width: "400", //幅 height: "300", //高さ background: "#FFFFFF", //背景色 version: "1.0" //Silverlight のバージョン }, { onError: null, //エラー時のイベントハンドラ onLoad: onLoadHandler //読み込み時のイベントハンドラ }, "Dote up a cat.", //初期化パラメータ "Kitty on your lap" //onLoad イベントに渡される値 ); </script> </body> </html>
<TextBlock xmlns="http://schemas.microsoft.com/client/2007"
FontSize="30" FontFamily="Comic Sans MS" Foreground="Red"
> Kitty on your lap </TextBlock>

コード05は、[OK]ボタンが押されるとテキストボックスに入力された文字列をSilverlight上に表示します。このSilverlightが読み込む「test.xaml」ファイルのルート要素に、TextBlockオブジェクトを指定しています。onLoad()イベントのsourceパラメータには、Silverlightに設定されているルートUIElementオブジェクトが格納されています。この変数はUIElementオブジェクトとの互換性が保証されますが、このプログラムの実行にはTextBlockオブジェクトであることが前提となります。これを変数として保存しておき、[OK]ボタンが押されたタイミングでTextプロパティにテキストボックスに入力されている値を設定することで、Silverlight上の文字を変更することができます。
他のあらゆるオブジェクトの操作方法も、基本的に同じです。オブジェクトの持つプロパティの名前は、XAMLの属性で指定した名前と同じなので、JavaScriptからオブジェクトを操作する場合でも、XAMLとSilverlightオブジェクトについて理解していれば簡単です。
動的なオブジェクトの生成
これまでは、Silverlightで表示する視覚的なオブジェクトをXAMLファイルで静的に宣言していました。開発時に、表示するオブジェクトを確定できるのであれば問題ありませんが、実行するまで表示するオブジェクトを確定できない場合、静的にインスタンスを宣言することはできません。例えば、Webベースの図形作成アプリケーションをSilverlightで実装するシナリオを考えてみてください。図形を作成するのはユーザーなので、XAMLであらかじめ図形を宣言しておくことは不可能です。この場合、インスタンスは実行時に、ユーザーの操作によって作られなければなりません。
Silverlight Plug-inオブジェクトは、動的なSilverlightオブジェクトの作成をサポートしています。動的なオブジェクトの生成にはCreateFromXaml()メソッドを使います。これはW3CのDOMで例えるならばDocumentインターフェイスのcreateElement()メソッドに相当する働きです。
retval = silverlightObject .content.CreateFromXaml(xamlContent[, createNameScope])
このメソッドは、Silverlight Plug-inオブジェクトのcontentサブオブジェクト内に格納されています。第1パラメータのxamlContentには、生成するオブジェクトのXAML表現による文字列を指定します。"<Ellipse .../>"と指定すればEllipseオブジェクトが生成され、"<Line .../>"と指定すればLineオブジェクトが生成されます。第2パラメータcreateNameScopeはオプションなので省略可能です。これは、他の要素の名前と衝突しないx:Name属性かどうかをBoolean型で指定します。デフォルトではfalseが指定されています。
x:Name属性は、スクリプトから要素を検索、および取得するための識別子を提供します。createNameScope属性にtrueが設定されている場合、複数の要素で同じ名前が使われていることを許容しますが、falseの場合は名前の衝突を許しません。もし、同じ名前の要素がある場合、Canvasに追加しようとした時点でエラーが報告されます。
UIElementオブジェクトは、生成しただけではSilverlightに関連付けられていないため表示されません。表示するSilverlightの階層内にある何らかのCanvasオブジェクトに追加して、初めて表示されます。スクリプトから動的にCanvas要素の子要素としてUIElementオブジェクトを追加するには、CanvasオブジェクトのChildrenプロパティを使います。
value = object.Children
XAMLでは意識する必要のなかったChildrenプロパティですが、スクリプトから操作する場合はChildrenプロパティを通してCanvasオブジェクトに格納されている子オブジェクトにアクセスします。このプロパティは読み取り専用で、任意の数のUIElementを子として管理するVisualCollectionオブジェクトを返します。このオブジェクトを明示的にインスタンス化することはありません。VisualCollectionオブジェクトは、CanvasオブジェクトのChildrenプロパティの戻り値としてのみ利用します。
このオブジェクトは、一種のUIElementのコレクションとして機能しています。現在保有しているUIElementの個数はCountプロパティから取得することができ、オブジェクトの追加はAdd()メソッドから、取得はGetItem()メソッドから、削除はRemove()メソッド、またはRemoveAt()メソッドから行うことができます。この場で重要なのは、生成したオブジェクトを追加するAdd()メソッドなので、他のVisualCollectionオブジェクトのメンバの詳細については割愛させていただきますが、実行時にオブジェクトの追加や削除を行ったり、または検索を行う場合には、VisualCollectionオブジェクトの機能を利用します。
retval = object.Add(value)
valueには、このVisualCollectionオブジェクトに追加するUIElementオブジェクトを指定します。追加されたオブジェクトは、このVisualCollectionオブジェクトを保有しているCanvasの子オブジェクトとして表示されます。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Silverlight test</title> <script type="text/javascript" src="Silverlight.js"></script> <script type="text/javascript"> function onLoadHandler(sender, context, source) { var brush = sender.content.CreateFromXaml("<SolidColorBrush />", false); brush.Color = "Black"; var ellipse = sender.content.CreateFromXaml( "<Ellipse Width=\"200\" Height=\"100\" />", false); ellipse.Stroke = brush; ellipse.StrokeThickness= 5; source.Children.Add(ellipse); } </script> </head> <body> <div id="silverlight"></div> <script type="text/javascript"> var parentElement = document.getElementById("silverlight"); Silverlight.createObject( "test.xaml", //ソースファイル parentElement, //Silverlight を表示するDIVタグのDOMオブジェクト "silverlight01", //任意の一意なプラグインID { width: "400", //幅 height: "300", //高さ background: "#FFFFFF", //背景色 version: "1.0" //Silverlight のバージョン }, { onError: null, //エラー時のイベントハンドラ onLoad: onLoadHandler //読み込み時のイベントハンドラ }, null, //初期化パラメータ null //onLoad イベントに渡される値 ); </script> </body> </html>
<Canvas xmlns="http://schemas.microsoft.com/client/2007">
</Canvas>

コード06は、Silverlightが初期化されonLoadHandler()関数が呼び出されたタイミングで、スクリプトから動的にCreateFromXaml()関数を使ってSolidColorBrushオブジェクトとEllipseオブジェクトを生成しています。生成されたオブジェクトは、XAMLファイルから生成したオブジェクトと同じです。オブジェクト生成後に必要なプロパティを設定し、最後にCanvasオブジェクトのChildrenプロパティから取得したVisualCollectionオブジェクトのAdd()メソッドで生成したオブジェクトを追加しています。
最後に
実行時にJavaScriptからオブジェクトを操作する方法を使えば、Webアプリケーションのプレゼンテーション部分をSilverlightオブジェクトを用いて自由に表現することができるようになります。これまで、HTML要素では難しかった動的なグラフや、絶対座標によるオブジェクトの自由な配置、座標変換、回転、マルチメディアなどを駆使した高度なプレゼンテーションをクライアント上で実現できるようになるのです。
ここで重要なのは、SilverlightがAjaxベースのWebアプリケーションと同じJavaScriptで操作できるということです。Ajaxベースのアプリケーションのコードが適切なMVCアーキテクチャに基づいて、データを表現するオブジェクトと、ロジックを提供するオブジェクト、そしてユーザーインターフェイスに分離されている場合、ユーザーインターフェイスを担当するコードを置き換えるだけでSilverlightに対応することができます。
参考
- MSDN 「Silverlight 1.0 Reference」
