.NET TIPS

[ASP.NET AJAX]ダイナミック・コンテキスト機能でポップアップ・コントロールの内容を動的に生成するには?[2.0、3.0、3.5、C#、VB]

山田 祥寛
2008/03/13

 「ダイナミック・コンテキスト機能」は、ASP.NET AJAX Control Toolkit(以降、Control Toolkit)で提供されている機能の1つで、ポップアップ・コントロールを表示する際にサービス・メソッドを実行して、その結果をポップアップ・コントロールに引き渡すためのものだ。

 この機能を利用することで、ポップアップ・コントロールの内容を(あらかじめ静的に決めておくのではなく)サービス・メソッドから動的に取得した結果に基づいて生成することが可能になる。PopupControlコントロールをはじめ、ModalPopupHoverMenuDropDownなど、ポップアップ機能を持つコントロールで、共通して利用することができる。

 本稿では、これらの中からDropDownコントロールを採用し、ドロップダウン(ポップアップ)・メニューをデータベースから動的に取得/生成する方法を紹介する。次の画面はその実行例である。


(「詳細はこちらを参照」にマウス・ポインタを当てドロップダウン・メニューを表示する)
データベースから取得したメニュー情報を基にポップアップ・メニューを表示

 それではさっそく、具体的な作成の手順を見ていく。なお、本サンプルを動作させるに当たっては、「TIPS:[ASP.NET AJAX]ASP.NET AJAX Control Toolkitを利用するには?」で紹介した手順に従って、Control Toolkitを利用可能な状態にしておく必要がある。

1. メニュー情報を表すMenuテーブルを作成する

 まずは、ポップアップ・メニューに表示するメニュー情報を管理するために、以下のようなMenuテーブルをデータベース上に作成しておこう。

フィールド名 データ型 概要
url VARCHAR(255) リンク先のURL(主キー)
title VARCHAR(100) メニューのタイトル
category VARCHAR(20) 分類
Menuテーブルのフィールド・レイアウト

 categoryフィールドは、実際にメニュー情報を抽出する際のキーとなる情報である(例えば、「ASP.NET」などメニューの内容を表す情報を持つものとする)。

 また、Menuテーブルにはサンプル・データとして、次のような適当なメニュー情報をあらかじめセットしておくものとする。

url title category
http://www.atmarkit.co.jp/fdotnet/ Insider .NET ASP.NET
http://www.web-deli.com/ WebDeli - ASP.NETツール集 ASP.NET
http://www.wings.msn.to/ サーバサイド技術の学び舎 - WINGS ASP.NET
http://my.yahoo.co.jp/ My Yahoo! Other
Menuテーブルのサンプル・データ

2. 新規のXML Webサービス・クラスを定義する

 ダイナミック・コンテキスト機能を利用するには、クライアント側からの要求に応じて何らかの処理を行い、その処理結果を文字列として返すようなXML Webサービス・クラスを用意しておく必要がある。

 以下は、クライアントから送信されたキー情報(ここではカテゴリ名)をキーにMenuテーブルを検索し、合致するメニュー情報をHTML形式(文字列)で返すASP.NET Webサービス(.asmxファイル)のコードだ。

<%@ WebService Language="C#" Class="DynamicContext" %>

using System;
using System.Configuration;
using System.Data;
using System.Data.Common;
using System.Text;
using System.Web;
using System.Web.Script.Services;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService()]
public class DynamicContext : System.Web.Services.WebService {
  [WebMethod]
  public string GetMenuContents(String contextKey) {

    StringBuilder result = new StringBuilder();

    ConnectionStringSettings setting =
      ConfigurationManager.ConnectionStrings["MyDB"];
    DbProviderFactory factory =
      DbProviderFactories.GetFactory(setting.ProviderName);

    using (DbConnection db = factory.CreateConnection()) {
      db.ConnectionString = setting.ConnectionString;
      DbCommand comm = factory.CreateCommand();

      // contextKeyパラメータ(分類名)をキーに
      // 合致するメニュー情報を取得
      comm.CommandText
        = "SELECT * FROM Menu WHERE category=@category";
      comm.Connection = db;
      DbParameter param = factory.CreateParameter();
      param.ParameterName = "@category";
      param.Value = contextKey;
      comm.Parameters.Add(param);

      db.Open();
      DbDataReader reader = comm.ExecuteReader();

      // 取得した結果セットを基に、
      // メニューに表示すべきアンカータグを生成
      while (reader.Read()) {
        result.Append(String.Format("<a href='{0}' style='color:Navy;font-size:Small;text-decoration:none;'>{1}</a><br />", reader["url"], reader["title"]));
      }
    }
    // 最終的に出来上がったStringBuilderオブジェクトを文字列に変換
    return result.ToString();
  }
}
<%@ WebService Language="VB" Class="DynamicPopulate" %>

Imports System.Data
Imports System.Data.Common
Imports System.Web
Imports System.Web.Script.Services
Imports System.Web.Services
Imports System.Web.Services.Protocols

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ScriptService()> _
Public Class DynamicPopulate
  Inherits System.Web.Services.WebService
 
  <WebMethod()> _
  Public Function GetMenuContents(ByVal contextKey As String) As String
    Dim result As New StringBuilder()

    Dim setting As ConnectionStringSettings = _
      ConfigurationManager.ConnectionStrings("MyDB")
    Dim factory As DbProviderFactory = _
      DbProviderFactories.GetFactory(setting.ProviderName)

    Using db As DbConnection = factory.CreateConnection()
      db.ConnectionString = setting.ConnectionString
      Dim comm As DbCommand = factory.CreateCommand()

      ' contextKeyパラメータ(分類名)をキーに
      ' 合致するメニュー情報を取得
      comm.CommandText _
        = "SELECT * FROM Menu WHERE category=@category"
      comm.Connection = db
      Dim param As DbParameter = factory.CreateParameter()
      param.ParameterName = "@category"
      param.Value = contextKey
      comm.Parameters.Add(param)

      db.Open()
      Dim reader As DbDataReader = comm.ExecuteReader()

      ' 取得した結果セットを基に、
      ' メニューに表示すべきアンカータグを生成
      Do While reader.Read()
        result.Append(String.Format("<a href='{0}' style='color:Navy;font-size:Small;text-decoration:none;'>{1}</a><br />", reader("url"), reader("title")))
      Loop
    End Using

    ' 最終的に出来上がったStringBuilderオブジェクトを文字列に変換
    Return result.ToString()
  End Function
End Class
クライアント側からの要求を処理するためのXML Webサービス・クラス(DynamicContext.asmx)(上:C#、下:VB)

 サンプル・アプリケーションの大まかな流れについては、コード内のコメントを参照していただくとして、ここで注目していただきたいのは、以下の2点だ(なお、ここではXML Webサービス・クラスそのものの記法については割愛する。詳細については、「MSDN:ASP.NETを使用したXML Webサービス」を参照していただきたい)。

(1)XML Webサービス・クラスにはScriptService属性を付与する

 ScriptService属性(System.Web.Script.Services名前空間)は、該当のXML Webサービス・クラスがクライアント側スクリプトから呼び出し可能であるかどうかを表すものだ。

 ダイナミック・コンテキスト機能は、内部的に自動生成したJavaScript経由でサーバ側のXML Webサービスと非同期通信を行うので、通信先となるXML Webサービス・クラスでは必ずScriptService属性を付与しておく必要がある。

(2)XML Webサービス・メソッドのパラメータ名、戻り値の型は固定

 ダイナミック・コンテキスト機能において、XML Webサービス・メソッドの名前は自由に決めることができるが(ここではGetMenuContents)、戻り値のデータ型およびパラメータの名前/データ型は完全に固定であり、アプリケーション開発者が変更することはできない。

 つまり、いかなる場合にもXML Webサービス・メソッドは以下のシグニチャに従う必要がある。C#/Visual Basic(VB)いずれを利用しているかにかかわらず、パラメータの名前は大文字/小文字まで厳密に区別されるので、注意してほしい。

[WebMethod()]
public String <メソッド名>(String contextKey)
<WebMethod()> _
Public Function <メソッド名>(ByVal contextKey As String) As String
ダイナミック・コンテキスト機能から呼び出されるXML Webサービス・メソッドのシグニチャ(上:C#、下:VB)

 XML Webサービス・メソッドがcontextKeyパラメータを介して受け取るのは、クライアント側からの任意のキー値だ。ダイナミック・コンテキスト機能では、このcontextKeyパラメータの値をキーに、処理を分岐したり、データベースなどへの問い合わせをしたりすることができる。

 本サンプルではcontextKeyパラメータとして、メニュー情報を抽出するためのカテゴリ名がセットされているものとする。ここでは、このカテゴリ名をキーとして、合致するメニュー情報のみを取り出し、アンカータグ(最終的な出力イメージ)として整形したものを戻り値として返しているわけだ。

[注意]

ダイナミック・コンテキスト機能では、XML Webサービス・メソッドのシグニチャの制限から、クライアントからは1つしかパラメータを受け取ることができない。もちろん、特定の区切り文字で連結した文字列を生成し、疑似的に複数のパラメータを表現するといったことは可能であるが、それにしてもコードの可読性/保守性をかんがみれば、あまりに複雑なパラメータ情報を引き渡すのは好ましくないだろう。

3. 新規のWebフォームを作成する

 新規のWebフォーム(DynamicContext.aspx)を作成したら、フォーム・デザイナから以下の画面の要領でサーバ・コントロールを配置する。また、それぞれのコントロールに対しては、表の内容でプロパティ値を設定しておこう。

Webフォーム(DropDown.aspx)のフォーム・レイアウト
フォーム上に配置するコントロールとそのプロパティ設定は以下のとおり。
コントロール(ID) プロパティ 設定値
ToolkitScriptManager(manager*1
Label(lblTitle) Text 詳 細 は こ ち ら を 参 照
Font-Size Small
Width 250px
Panel(popup) BackColor Gainsboro
BorderColor Black
BorderStyle Solid
BorderWidth 1px
Wrap False
Label(lblMenu) Text △(ブランク)
DropDownExtender(dde) TargetControlID lblTitle
DropDownControlID popup
HighlightBackColor 192, 192, 255
HighlightBorderColor 0, 0, 64
DynamicControlID lblMenu
DynamicContextKey ASP.NET
DynamicServiceMethod GetMenuContents
DynamicServicePath DynamicContext.asmx
CacheDynamicResults True
*1 ToolkitScriptManagerコントロールは、Control Toolkitを利用する場合に必ず必要となるコントロール。詳細については、「TIPS:[ASP.NET AJAX]AlwaysVisibleControlコントロールで常時表示されるパネルを定義するには?」を参照してほしい。

 DropDownコントロールの基本的なプロパティ設定については、「TIPS:[ASP.NET AJAX]DropDownコントロールでSharePoint風のドロップダウン・メニューを作成するには?」をご参照いただくとして、ここではダイナミック・コンテキスト機能にかかわる以下のプロパティに注目してみよう*2

プロパティ 概要
DynamicControlID サービス・メソッドからの戻り値を反映する要素のID値
DynamicContextKey サービス・メソッドに引き渡すコンテキスト・キー
DynamicServiceMethod サービス・メソッドの名前
DynamicServicePath XML Webサービス・クラスのパス
CacheDynamicResults サービス・メソッドからの結果をキャッシュするか(デフォルトはFalse)
ダイナミック・コンテキスト機能に関係するプロパティ

*2 これらのプロパティは、ダイナミック・コンテキスト機能に対応したすべてのコントロールで共通して利用できる。

 これらの説明を念頭に、本サンプルでの設定を見直してみると、「ポップアップするタイミングでGetMenuContentsメソッド(DynamicContext.asmx)にアクセスし、その戻り値をラベル(lblMenu)に反映させる」ということになる。また、先ほどの繰り返しであるが、DynamicContextKeyプロパティで指定された「ASP.NET」はMenuテーブルからメニュー情報を抽出する際に使用するキー情報である。

 以上を理解したら、さっそく作成したサンプル・プログラムを実行してみよう。冒頭の画面のように、ラベルテキストをクリックすることで、Menuテーブルから抽出されたメニュー情報が表示されれば成功だ。End of Article

利用可能バージョン:.NET Framework 2.0
利用可能バージョン:.NET Framework 3.0
利用可能バージョン:.NET Framework 3.5
カテゴリ:Webフォーム 処理対象:ASP.NET AJAX
使用ライブラリ:PopupControlコントロール
使用ライブラリ:ModalPopupコントロール
使用ライブラリ:HoverMenuコントロール
使用ライブラリ:DropDownコントロール
関連TIPS:[ASP.NET AJAX]ASP.NET AJAX Control Toolkitを利用するには?
関連TIPS:[ASP.NET AJAX]AlwaysVisibleControlコントロールで常時表示されるパネルを定義するには?
関連TIPS:[ASP.NET AJAX]PopupControlコントロールで標準コントロールにポップアップ機能を追加するには?
関連TIPS:[ASP.NET AJAX]ModalPopupコントロールでモーダル・ウィンドウを生成するには?
関連TIPS:[ASP.NET AJAX]HoverMenuコントロールでマウス・ホバー時に表示されるポップアップ・メニューを定義するには?
関連TIPS:[ASP.NET AJAX]DropDownコントロールでSharePoint風のドロップダウン・メニューを作成するには?

この記事と関連性の高い別の.NET TIPS
[ASP.NET AJAX]DynamicPopulateコントロールでXML Webサービスを非同期に呼び出すには?
[ASP.NET AJAX]クライアントサイド・スクリプトからXML Webサービスを非同期呼び出しするには?(サーバサイド編)
[ASP.NET AJAX]AutoCompleteコントロールでGoogleサジェスト風なオートコンプリート機能を実装するには?
[ASP.NET AJAX]DropDownコントロールでSharePoint風のドロップダウン・メニューを作成するには?
[ASP.NET AJAX]ダイナミック・コンテキスト機能で構造化データを受け渡しするには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間