次の方法で共有


Cutting Edge

ASP.NET AJAX 4.0 におけるライブ データ バインド

Dino Esposito

最近、新しいオフィスに引っ越しました。このとき、10 年以上に渡って集めてきたプログラミング関連の書籍をすべて荷造りするという、とてもうれしく、わくわくするような経験をしました。

これらの書籍から、Web プログラミングがここ 10 年に進化してきた過程が明らかになります。互いに改良を加えながら (多くの場合、革新的な変更が加えられ)、それぞれのテクノロジが次へと繋がって進化していくようすがよくわかります。

とりわけ、1 冊の書籍が私の注意を引きました。Internet Explorer 4 向けの (その当時の) 最先端プログラミング技術が取り上げられている書籍です。私はそのページをめくりたい気持ちを抑えることができませんでした。

1990 年代後半に、コンピューター業界で最も著名な人々によって、Web とブラウザーを動的でプログラミング可能な環境にしようとする最初の試みが行われました。

データ バインドも、現在普及している多くの機能の中で、当時、研究や開発が行われていた機能の 1 つでした。ここ数年、データ バインドの基本的な考え方はそれほど大きく変化していませんが、Web の世界のアプリケーションに関する限り、本質的な変換が行われました。Web 上にデータ バインドを実装する一般的なアプローチは、現在と 1990 年代後半とでは根本的に異なっています。その違いの多くは AJAX (Asynchronous JavaScript and XML) によるものです。

今月のコラムでは、ASP.NET AJAX 4.0 によってもたらされる、クライアント側でのデータ バインドのさまざまな形式について説明します。具体的には、データ バインドと監視可能なオブジェクトについて、いくつか高度な機能を中心に説明します。

基本原理

大まかに表現すれば、データ バインドとは、対象とするコンポーネントのメンバーとデータ ソースのメンバーとを結び付けるプログラム機能です。Microsoft Access や Microsoft Visual Basic などの RAD (Rapid Application Development) ツールによって、データ バインドが実現されました。

RAD ツールにより、表示要素とデータ ソースのメンバーを結び付けるための、簡単かつ効率的なインフラストラクチャが開発者に提供されました。長い間、データ ソースは、SQL クエリによって得られるレコードセットのデータ ストリームと考えられていました。

このことは、スマート クライアントのシナリオにはうまく適合しますが、Web クライアントのシナリオでは問題が発生します。たとえば、レコードを保持するデータベース サーバーから JavaScript を使って要求を行っているブラウザーにレコードを受け渡すにはどうすればよいでしょう。

何年も忘れていたその古い書籍を開いてみると、TDC (Tabular Data Control: 表形式データ コントロール) やリモート データ サービス (RDS) といった、とてもわかりやすい名前の付いた特殊な ActiveX コンポーネントを基にした、IE4 のデータ バインド機能について説明されていました。図 1 は、動的な Web に着手した時代に IE4 のアーキテクトが想定していた、クライアント側でのデータ バインド アーキテクチャの全体像を示しています。

図 1 Internet Explorer 4 におけるクライアント側データ バインド

データ バインドを目的に作成された ActiveX コントロールは、リモート データ ソースとの接続を管理し、データのダウンロードを行います。必要であればデータのキャッシュも行います。RDS を使用する場合、データ ソースは ODBC 準拠のデータ ソースです。TDC を使用する場合は、サーバー側のテキスト ファイルです。

バインド元要素とバインド先要素を実際に結び付けるのは、datasrc、datafld、dataformatas などのブラウザー固有の HTML 属性です。次に、簡単な例を示します。

<span id="Label1" datasrc="#rdsCustomers" datafld="CompanyName" />

結果のドキュメント オブジェクト モデル (DOM) では、バインドされているフィールドの内容 (この例では CompanyName) が SPAN タグ用に予約されている領域に置き換わります。

DOM に実際にデータを挿入するのは何でしょう。前述のとおり、この場合は、ブラウザーがこの処理を実行します。ブラウザーが dataXXX 属性を検出すると、内部で取り決めた API を使用してデータ ソース コントロールにデータを照会します。その後、取得したすべてのデータを最終形式となる DOM に挿入し、ユーザーに表示します。

おわかりのように、このソリューションはブラウザーとの結び付きが緊密になるため、当然のことながら、開発者の心をつかむことはありませんでした。

その後、クライアント側データ バインドは数年間放置され、ASP.NET のようなサーバー側プログラミング モデルが広く受け入れられてきました。

最近になって、AJAX の登場によりクライアント側データ バインドに大きな関心が寄せられ、エンジニアはクライアント側データ バインドを実行するための効率的な方法 (今回はブラウザーを意識しないで使用できる方法) をまた模索するようになりました。

ASP.NET AJAX における進化

図 2 は、ASP.NET AJAX 4.0 で実装されるクライアント側データ バインド アーキテクチャの全体像を示しています。

図 2 ASP.NET AJAX 4.0 におけるクライアント側データ バインド

図 1図 2 に示すアーキテクチャは一見同じように見えますが、実際には、いくつかの重要な側面が異なります。

何よりもまず、ASP.NET AJAX 4.0 では、現在使用されているあらゆるブラウザーで機能するクライアント側データ バインド ソリューションを構築できます。ソース データと対象要素を実際に結び付けるために必要なコードは、Microsoft Ajax JavaScript ライブラリに含まれるようになりました。このため、ソリューションをあらゆるブラウザーでホストすることができます。

また、ブラウザーはバインドを実行するために解決しなければならなかった、標準ではない専用の HTML 属性 (datasrc や datafld など) を使用する必要がなくなりました。代わりに、バインド情報はXHTML 準拠の名前空間付きのカスタム属性を使用して指定されるようになり、こうした属性は JavaScript ライブラリのコードから解決されます。バインド情報の指定は、命令として記述することもできます。

従来のスタイルと新しいスタイルの比較

もう 1 つの重要な違いは、データ ソース オブジェクトの構造にあります。従来のデータ バインドでは、プロキシがデータの取得を管理しており、このプロキシはある種ブラック ボックスでした。ASP.NET AJAX 4.0 では、そのような ActiveX コンポーネントやバイナリ コンポーネントは必要ありません。必要なのは、JavaScript オブジェクトとソース データだけです。

組み込みのバインド インフラストラクチャが、JavaScript のソース オブジェクトのフィールドと DOM 要素を結び付けます。

ASP.NET AJAX 4.0 では、このようなバインド インフラストラクチャは Sys.UI.DataView コンポーネントに組み込まれています。DataView オブジェクトの機能は、IE4 スタイルのクライアント側データ バインドにおける RDS コントロールの機能とほぼ同じで、リモート エンドポイントに直接接続して、データを取得および公開します。

ただし、いくつか違いがあります。DataView オブジェクトは、すべてが JavaScript で記述されているクライアント コントロールなので、ブラウザーにこれを実行するための特殊なサポートは必要ありません。このように、RDS ActiveX コントロールとは大きく異なっています。

さらに、DataView コントロールは、リレーショナル データ ソースと直接インターフェイスを取ることはありません。JavaScript Object Notation (JSON) や JSON With Padding (JSONP) 対応の任意のサービス (Windows Communication Foundation エンドポイントなど) に接続し、JSON を使用してデータを交換します。サービスは、あらゆる物理データ ストア (リレーショナル データベースなど) をラップしたり、Entity Framework モデルに基づくプレーンなラッパーにすることもできます。図 2 に示すように、ASP.NET AJAX 4.0 では、サーバーへの送信ネットワーク接続なしに、データ バインドを実行することもできます。たとえば、ページの読み込み時に、なんらかのデータをクライアント コンピューターにダウンロードする場合、サーバーへのラウンドトリップを増やすことなく、ローカルにキャッシュしているデータを使ってデータ バインドを実行できます。

簡単な要約

2009 年 10 月号の Cutting Edge コラム (msdn.microsoft.com/ja-jp/magazine/ee309508.aspx) では、開発者の視点から、ASP.NET AJAX 4.0 のデータ バインドの基礎について説明しました。このコラムを参照して詳しい内容を把握することもできますが、ここでは、クライアント側データ バインドの最も重要なプログラミング事項を簡単にまとめます。

ASP.NET AJAX 4.0 のクライアント側データ バインドは、対応する HTML テンプレート内で行われます。テンプレートは、sys-template CSS 属性で装飾される DOM ツリーです。

<div sys:attach="dataview1" class="sys-template">  
   ...
</div>

sys-template は、ユーザー定義の CSS スタイルの標準名で、最も短い形式は次のようになります。

<style type="text/css">
   .sys-template { display:none; }
</style>

しかし、sys-template 属性で特定の HTML タグを修飾するだけでは不十分です。なんらかのビヘイビアをタグに追加して、タグ内のバインド式を処理できるようにする必要があります。この場合、ビヘイビアとは、バインド式を処理することを目的とした JavaScript コンポーネントやコントロールのインスタンスにすぎません。

ビヘイビアを HTML タグにアタッチするには、プログラムでビヘイビアのインスタンスを作成するか、(ページのテンプレート タグにマークアップを追加して) 宣言型の手法を使用します。宣言型手法では、ビヘイビアはパブリック名 (名前空間プレフィックス) に関連付けられていなければなりません。

ここで、DataView コンポーネントのインスタンスにパブリック名を割り当てる例を示します。

<body xmlns:sys="javascript:Sys" 
      xmlns:dataview1="javascript:Sys.UI.DataView">
...
</body>

sys:attach 属性がパブリック名を受け取って、参照先のビヘイビア オブジェクトのインスタンスを作成します。1 つ目のコード サンプルでは、dataview1 というオブジェクトで表されるビヘイビアによって、DIV タグに機能を追加しています。ご想像のとおり、dataview1 は、Sys.UI.DataView JavaScript オブジェクトの単なるパブリック名です。

DataView インスタンスが ASP.NET AJAX 4.0 テンプレートにアタッチされると、DataView はテンプレート内に含まれるすべてのバインド式を正しく処理できます。最も単純なバインド構文を使用するサンプル テンプレートを次に示します。

<ul id="imageListView" class="sys-template" 
     sys:attach="dataview1" 
    dataview1:data="{{ imageArray }}">
    <li>
        <span>{{ Name }}</span>
        <span>{{ Description }}</span>
    </li>
</ul>

{{式}} というトークンは、そこに埋め込まれている JavaScript 式を処理し、その結果を DOM や指定した DataView プロパティに代入するよう、DataView に指定します。たとえば、上記のコードでは、imageArray という JavaScript 変数の内容を、DataView の data というプロパティに代入します。このような方法で、バインド操作のデータ ソースを定義します。この情報は、テンプレート内の他のバインド式 (上記本文の 2 つの SPAN タグで使用されている式) を拡張するのに使用します。Name と Description は、DataView の data プロパティに代入されるデータ項目 (1 つ以上) のパブリック プロパティになります。

インライン式の評価

{{式}} 構文は、ASP.NET AJAX 4.0 でサポートされる最も単純な形式のバインドを示しています。このように表されるバインドは、テンプレートがレンダリングされるときにのみ評価されます。また、テンプレートがプログラムで更新されない限り、これらのバインドも更新されません。

インライン式は、レンダリング時にデータ ソースの現在状態に照らして評価されますが、データ ソースに対するそれ以降の変更が自動的にキャプチャされることはありません。

そのため、これ以外に機能が豊富なバインド モデルもサポートされます。このようなバインド モデルにより、Windows Presentation Foundation アプリケーションや Silverlight アプリケーションにおける XAML データ バインドと同等のプログラミング機能がもたらされます。こうした一連の高度なデータ バインド機能を一般に "ライブ バインド" と呼びます。では、詳しく見ていくことにしましょう。

ライブ バインド

データ ソース内のバインド値が変更されると、ユーザー インターフェイスに表示されている値が自動的に更新されるのが、ライブ バインドです。たとえば、SPAN タグとデータ ソースの CompanyName プロパティとの間でライブ バインドを確立するとします。SPAN タグは、レンダリング時に CompanyName プロパティのその時点の値を表示します。ただし、バインド先のデータ ソースのプロパティが変化すると、SPAN タグの内容も自動的に更新されます。ライブ バインドは、DOM 要素か JavaScript オブジェクトかに関係なく、任意の 2 つのオブジェクト間に適用できます。

ライブ バインドの式の構文は他の構文とは異なります。その例を次に示します。

<span>{binding CompanyName}</span>

中かっこで式を囲み、式のプレフィックスとしてキーワード binding を付けます。このように、構文全体は、対応する XAML 構文と多くの共通点があります。これは偶然ではありません。

先ほどの SPAN タグの内容は、現在のバインド先のデータ項目で変更を検出すると自動的に更新されます。ただし、その逆は機能しないため注意が必要です。つまり、SPAN タグの内容が更新されても、その変更はソース オブジェクトに反映されません。

ライブ バインドは、データ ソースで更新が検出されたときに繰り返し行われる一方向バインドとも言えます。

さて、バインドでの変化を検出するために採用する方針が重要なポイントとなるため、これについてすぐにでも説明しなければならないことがあるのですが、その前に双方向バインドについて触れておきます。

双方向データ バインド

双方向データ バインドは、バインドでの変化を検出するために 2 つのチャネルを使用する、特殊な形式のライブ バインドです。2 つのオブジェクト間を双方向にバインドすると、次のことが行われます。

  • データ ソースが変化すると、対象となるオブジェクトが自動的に更新されます。
  • 対象となるオブジェクトが変化すると、新しい状態が基になるデータ ソースに反映されます。

つまり、双方向データ バインドでは、バインド元オブジェクトとバインド先オブジェクトの同期が常に保たれます。

複数の層に影響しない

次に示す内容はわかりきったことだと思われるかもしれませんが、とにかく、明らかにしておきます。サービスがデータベースから取得するなんらかのデータとユーザー インターフェイスとの間で双方向バインドを行っているとします。

サーバーからダウンロードされてユーザー インターフェイスの表示要素にバインドされるデータは、ドメイン モデルのスナップショット (Customer オブジェクトなど) を表します。双方向バインドを行っているページに表示されている Customer オブジェクトを変更すると、検出されたすべての変更はクライアント側の Customer オブジェクトに反映されます。しかし、サーバーに反映されることはありません。つまり、双方向バインドが複数の層に影響を与えることはありません。

双方向バインドの構文は、一方向ライブ バインドとほぼ同じです。

ASP.NET AJAX のバインドは、Sys.Binding JavaScript オブジェクトによって表されます。データが流れる方向は、ライブ バインドの構文を使用するときにフレームワークが必ず作成する、Sys.Binding オブジェクトの mode 属性を使用して制御します (ただし、単純な {{...}} インライン式を選択すると Sys.Binding オブジェクトは作成されません)。

次のコード スニペットは、mode 属性を使用して双方向データ バインドを設定する方法を示しています。

<span id="Label1">{binding CompanyName, mode=twoWay}></span>

図 3 に、mode 属性に使用できる値をまとめます。

メンバー 説明
auto 0 対象が INPUT 要素、SELECT 要素、TEXTAREA 要素、または Sys.INotifyPropertyChange インターフェイスを実装するコンポーネントであれば、データの流れは双方向 (twoWay) になります。それ以外は、一方向 (oneWay) です。
oneTime 1 テンプレートがレンダリングされるときに、データがバインド元オブジェクトからバインド先オブジェクトに 1 回だけ転送されます。
oneWay 2 バインド元オブジェクトが更新されると、毎回、バインド元オブジェクトからバインド先オブジェクトにデータが転送されます。
twoWay 3 バインド元オブジェクトが更新されると、毎回、バインド元オブジェクトからバインド先オブジェクトにデータが転送され、バインド先オブジェクトが更新されると、毎回、バインド先オブジェクトからバインド元オブジェクトにデータが転送されます。
oneWaytoSource 4 バインド先オブジェクトが更新されると、毎回、バインド先オブジェクトからバインド元オブジェクトにデータが転送されます。

図 3 Sys.BindingMode の列挙値

ライブ バインドの動作

図 4 は、双方向ライブ データ バインドの例を示すサンプル コードです。このページには、DataView コントロールを使用してレンダリングされる 1 つのテンプレートが含まれています。データ ソース オブジェクトは、theCustomers という JavaScript 配列です。theCustomers がクライアントのブラウザー内で静的に定義されているローカル オブジェクトであることに惑わされないでください。重要なのは、最終的に theCustomers が DataView オブジェクトの data プロパティに代入されることです。DataView オブジェクトは多くのプログラミング インターフェイスを備えているため、あらゆるコンテンツ (Web サービスからダウンロードしたコンテンツなど) を data プロパティに代入できます。

<asp:Content ID="Content2" runat="server" ContentPlaceHolderID="PH_Head">
  
    <link rel="stylesheet" type="text/css" 
      href="../../Css/lessantique.css" />
    <style type="text/css">
        .sys-template { display:none; }
    </style>
    
    <script type="text/javascript">
        var theCustomers = [
           { ID: "ALFKI", CompanyName: 
            "Alfred Futterkiste" },
           { ID: "CONTS", CompanyName: 
           "Contoso" }
        ];
    </script>
</asp:Content>    

<asp:Content ID="Content5" 
  ContentPlaceHolderID="PH_Body" 
  runat="server">

    <asp:ScriptManagerProxy  
    runat="server">
        <Scripts>
          <asp:ScriptReference Path=
"https://ajax.microsoft.com/ajax/beta/0910/MicrosoftAjaxTemplates.js" />
        </Scripts>
    </asp:ScriptManagerProxy>

    <div id="customerList">
       <ul class="sys-template" 
         sys:attach="dataview" dataview:data="{{ theCustomers }}">
         <li>
           <span><b>{binding ID}</b></span>
           <input type="text" id="TextBox1" 
             value="{binding CompanyName}" /> 
           <br />  
           <span>Currently displaying... 
<b>{binding CompanyName}</b></span>  
         </li>
       </ul>
    </div>
</asp:Content>

図 4 双方向ライブ バインドの例

バインドされるデータ項目ごとに、テンプレートによってテキスト ボックスを含む LI タグが出力されます。このテキスト ボックスが、データ ソースの CompanyName プロパティにバインドされます。同じテンプレートで、SPAN タグもデータ ソースの CompanyName プロパティにバインドされます。

ライブ バインドを実行できるのは、所属しているテンプレートに限定されません。たとえば、{binding CompanyName} といった式を、2 つの異なるテンプレートで使用することができます。両方のテンプレートに同じデータ ソース オブジェクト (または互換性のあるオブジェクト) がアタッチされる限り、バインドは常に適切に解決されます。図 5 に、実行中のページを示します。

図 5 実行中のライブ バインド

最初は、テキスト ボックスと SPAN タグに同じデータが含まれています。しかし、ある時点で、ユーザーがテキスト ボックス内の会社名を編集し始めるとします。テキスト ボックスからフォーカスがなくなるまでは何も起こりません。

テキスト ボックスからフォーカスがなくなると、編集は完了したものと見なされます。この時点で、双方向データ バインドのメカニズムがトリガーされ、基になるデータ ソース オブジェクトが更新されます。SPAN タグも、ライブ バインドによって同じ data プロパティにバインドされているため、すべての変更が反映されます。

INPUT 要素が含まれているときに、データ ソースが自動的に更新されないようにするには、mode プロパティを明示的に次のように設定します。

<input type="text" value="{binding CompanyName, mode=oneWay}" />

この変更を図 4 のコードに入力すると、違いがわかります。

変化を検出する

バインドの mode プロパティが明示的に設定されていなければ、図 3 に示した auto 値が使用されます。入力シナリオを表す HTML 要素 (INPUT、SELECT、TEXTAREA など) にバインドをアタッチすると、mode プロパティは既定で twoWay に設定されます。その結果、ブラウザーのユーザー インターフェイスを使用して行われるバインド先オブジェクトへのすべての変更は、バインド元オブジェクトに自動的に転送されます。

oneWay バインドには、2 つのバリエーションがあります。標準の oneWay バインドでは、バインド元の変化を検出して、ユーザー インターフェイスにその変化を反映します。もう 1 つの oneWayToSource では、これとは逆の動作が行われます。つまり、バインド先オブジェクトの変化を検出して、バインド元オブジェクトに反映します。次のコードを試してみてください。

<input type="text" value="{binding CompanyName, mode=oneWayToSource}" />

最初は、ページに空のテキスト ボックスが表示されます。ただし、新しくテキストを入力すると、そのテキストが検出され、予想どおりに処理されます。

また、双方向データ バインドは、Sys.INotifyPropertyChange インターフェイスを実装する JavaScript オブジェクトをバインドする場合の既定のオプションです (このインターフェイスは、Microsoft Ajax JavaScript ライブラリに含まれています)。

ライブ バインドの最初の紹介で、バインド元オブジェクトが変化すると、バインド先オブジェクトが更新されることを説明しました。次に、フレームワークが検出できる変化の種類と、そのしくみについて説明します。

HTML の INPUT 要素は、要素の状態が変化すると標準のイベントを発生します。少なくとも、編集の開始時と終了時に通知を行います。こうしたイベントは HTML 標準に含まれているため、この標準に基づくデータ バインド ソリューションは、あらゆるブラウザーで機能します。

バインドの一方での更新がもう一方に反映されるようにするには、検出可能な方法でバインドを実行する必要があります。次のように、バインド元が JavaScript 配列だとします。

<ul class="sys-template" sys:attach="dataview" 
    dataview:data="{{ theCustomers }}">
  <li>
     <span ><b>{binding CompanyName}</b></span>
  </li>
</ul>

配列内のオブジェクトの CompanyName プロパティを更新してみます。次のマークアップは、クリック時に JavaScript の enterChanges 関数を実行するボタンを表示します。

<span>{binding CompanyName}</span>
<input type="button" value="Enter changes" 
onclick="enterChanges()" />
...
<script type="text/javascript">
    function enterChanges() {
        theCustomers[0].CompanyName = 
       "This is a new name";
    }
</script>

enterChanges 関数は、配列内の先頭オブジェクトの CompanyName プロパティを更新します。ご覧のように、これがバインド先オブジェクトの状態を更新する操作であることは明らかです。

ライブ バインドの場合は、新しい値が SPAN タグに表示されることを期待します。しかし、値を変更しても、何も起こらないことがわかります。

これは、従来のプレーンな JavaScript のようなオブジェクトで行われる更新を、ブラウザー間で通知する方法が存在しないためです。そのため、変化が起きていますが、バインドがその変化を認識しないため、ユーザー インターフェイスは更新されません。

プレーンな JavaScript オブジェクトの状態をポーリングすることが実用的な解決策となるでしょうか。おそらくそうではありません。開発チームは、主にスケーラビリティ上の理由から、そのようなオプションを当然のごとく除外します。

結局、他のライブ バインドが適切にトリガーされるようにデータを変更するには、HTML の INPUT 要素を使用してデータにバインドするしかないのでしょうか。そんなことはありません。Microsoft Ajax JavaScript ライブラリには、任意の JavaScript オブジェクトの変化を "認識" できる、静的 API があります。この API では、バインド メカニズムで更新を検出するために、プレーンな JavaScript オブジェクトを監視可能なオブジェクトに変換する方法も利用できます。

監視可能な JavaScript オブジェクト

監視可能な JavaScript オブジェクトとは、変更が行われたときに変更を通知する付加機能が備わっているオブジェクトです。この付加機能は、Sys.Observer インターフェイスを使用した場合に機能します。インターフェイスを使用しないで直接変更すると、変更の通知が行われず、バインド インフラストラクチャに無視されます。

監視可能なオブジェクトは、表示要素と JavaScript オブジェクト (リモート Web サービスから取得する JavaScript オブジェクトなど) との間でライブ バインドを確立するようなシナリオに適しています。

監視可能なオブジェクトを機能させる方法は 2 つあります。1 つは、オブジェクトになんらかの動的コードを追加して、特定のオブジェクトを監視可能にします。動的コードといっても、プレーンな JavaScript オブジェクトを複雑にするほどではなく、新しい機能を追加する程度のことです。次に例を示します。

<script type="text/javascript">
    var theCustomers = [
            { ID: "ALFKI", CompanyName: 
            "Alfred Futterkiste" },
            { ID: "CONTS", CompanyName: 
            "Contoso" }
        ];    
    function pageLoad() {
        Sys.Observer.makeObservable(theCustomers);
    }
    
    function onInsert() {
        var newCustomer = { ID: "ANYNA", 
        CompanyName: "AnyNameThatWorks Inc" };
        theCustomers.add(newCustomer);
    }
</script>

Sys.Observer.makeObservable メソッドは、JavaScript オブジェクト (配列を含む) を受け取り、メソッドを追加します。このメソッドを使用してオブジェクトを変更すると、その変更をバインドから検出できるようになります。配列を監視可能にする場合、配列を監視可能な方法で変更するためのメソッドが提供されます。したがって、挿入や削除を検出できます。しかし、配列内の個々の項目のプロパティを監視可能な方法で変更するために、各プロパティに対応するメソッドが自動的に提供されるわけではありません。これを可能にするには、個々の項目に対して makeObservable を別々に呼び出し、各項目にメソッドが追加されるようにします。

既に説明したように、クリック イベントと関連付けられた次のコードでは、バインドがトリガーされません。

<script type="text/javascript">
    function enterChanges() {
        theCustomers[0].CompanyName = 
        "This is a new name";
    }
</script>

ただし、次のコードでは、バインドがトリガーされます。

<script type="text/javascript">
    function enterChanges() {
       System.Observer.setValue(theCustomers[0], 
       "CompanyName", "New name");
    }
</script>

監視対象のオブジェクトに子オブジェクトが含まれていても、問題ありません。setValue メソッドは、ピリオドを含む構文の処理方法を認識します。

System.Observer.setValue(theCustomers[0], "Company.Address.City", "Rome");

最後に、Web ページのコンテキストで遭遇するすべてのオブジェクト (DOM 要素、ビヘイビア、ウィンドウなどのブラウザー オブジェクトなど) に observer パターンを適用できることに注意してください。

静的バインドと動的バインド

アプリケーションでデータ バインドを必要とするときは、双方向バインドは必要としなくても、少なくとも一方向ライブ バインドを必要とすることがほとんどです。ASP.NET AJAX 4.0 では、静的データ バインドと動的データ バインドを使用できます。静的データ バインドでは、レンダリング中にデータ値の単純なインライン評価を行います。動的データ バインドでは、バインド元オブジェクトやバインド先オブジェクトでの変化を検出して、その変化を適用できます。ただし、必ずしもすべての更新が検出されて、バインドの更新に使用されるわけではありません。ASP.NET AJAX 4.0 では、表示要素を通じて、バインド対象のオブジェクトの変化を簡単に認識できます。しかし、プログラムから JavaScript オブジェクトや配列に変更が行われた場合、ブラウザー間でその変化をリアルタイムに検出するための信頼できる方法がありません。ASP.NET AJAX の手法は、オブジェクトを監視可能にし、ライブ バインドから検出できるようにする方法を提供することで成り立っています。これは、なんらかの監視可能な操作をオブジェクトに追加するか、それとは別に、アドホックな Sys.Observer 静的メソッドを使用して更新を実行するという形式になります。

Dino Esposito は、近々発売される『Programming Microsoft ASP.NET MVC』(Microsoft Press、2010 年) を執筆しました。Esposito はイタリアに在住し、世界各国で開催される業界のイベントで頻繁に講演しています。ブログは weblogs.asp.net/despos (英語) です。

この記事のレビューに協力してくれた技術スタッフの Dave Reed と Boris Rivers-Moore に心より感謝いたします。