SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

japan.internet.com翻訳記事

ListItemの属性をレンダリングできるWebカスタムコントロールの作成

CheckBoxListコントロールを拡張して項目に属性を追加する

  • このエントリーをはてなブックマークに追加

ASP.NET 1.xのリストコントロールの難点として、項目属性がレンダリングされないことが挙げられます。本稿では、まず、リストコントロールがレンダリングされる仕組みを理解した上で、リストコントロールのListItemインスタンスの属性もレンダリングされるようにリストコントロールクラスを拡張する方法を見ていきます。

  • このエントリーをはてなブックマークに追加

はじめに

 ASP.NET 1.xには、リストコントロールとして使えるWebコントロールが4つあります。

  • DropDownList
  • CheckBoxList
  • RadioButtonList
  • ListBox

 いずれもSystem.Web.UI.WebControls.ListControlクラスから派生したコントロールで、任意の数のListItemインスタンスを表示できます。その限りでは、4つとも基本的に同じものと言えますが、各コントロールの本体とその関連ListItem群のレンダリング方法はそれぞれ異なっています。たとえば、CheckBoxListの場合は本体がHTMLの<table>としてレンダリングされ、表のセル内にはCheckBox Webコントロールが配置されますが、DropDownListの場合は本体がHTMLの<select>要素、各ListItem<option>要素としてレンダリングされます。

 ただ、どのコントロールにも共通する難点として、「項目属性がレンダリングされない」という事実があります。たとえば、CheckBoxListを表示し、リスト中のいくつかのCheckBoxを特定のCSSクラスで表示したいとしましょう。あるいは、RadioButtonListコントロール中の特定のRadioButtonが選択されたときに、何らかのクライアント側JavaScriptが実行されるようにしたいとします。一般的には、CheckBoxまたはRadioButton WebコントロールのAttributesコレクションを使って設定できる機能ですが、残念なことに、リストコントロールのレンダリングでは、項目属性がレンダリングされません。

 本稿では、まず、これらのリストコントロールがいったいどのようにレンダリングされるのかを理解した上で、リストコントロールのListItemインスタンスの属性もレンダリングされるようにリストコントロールクラスを拡張する方法を見ていきます。最後にちょっとしたデモがありますから、これも見てください。このデモでは、CheckBoxListの中に[None]というチェックボックスオプションを用意しており、このチェックボックスをオンにすると、クライアント側スクリプトが実行されて、リスト内の他のチェックボックスが自動的にオフになります。この機能の実装方法については、続きをお読みください。

リストコントロールのレンダリング

 ASP.NET 1.xでは、RadioButtonListおよびCheckBoxListのレンダリング方法は、ListBoxおよびDropDownListのレンダリング方法とは少し異なります。RadioButtonListとCheckBoxListは、ListItemのレンダリングにSystem.Web.UI.WebControls.RepeatInfoクラスを使用します。RepeatInfoクラスは、HTMLの<table>内に項目群を垂直方向または水平方向にレンダリングします。ただし、RepeatInfoクラスは外側のHTML <table>のレンダリングだけを担当するという点に注意してください。内部要素のレンダリング処理は、外から与えられるオブジェクト(IRepeatInfoUserインターフェイスを実装しているもの)によって行われます。次の図は、RepeatInfoクラスによるデータレンダリングの流れを示しています。

 ご覧のとおり、RepeatInfoクラスは、RenderRepeater()メソッドに渡されるIRepeatInfoUser実装オブジェクトにレンダリングの多くの部分を代行させます。IRepeatInfoUserインターフェイスには、HasHeaderHasFooterRepeatedItemCountなどの諸プロパティと、実際に項目のレンダリングを行うRenderItem()メソッドが定義されています。

 CheckBoxListとRadioButtonListは、このIRepeatInfoUserインターフェイスを自身で実装しています。したがって、WebコントロールがRepeatInfoクラスのRenderRepeater()メソッドに引き渡すものは、自身のインスタンスに他なりません。つまり、CheckBoxListとRadioButtonListはどちらもIRepeatInfoUserインターフェイスの必要なプロパティとメソッドを実装しているということです。CheckBoxListとRadioButtonListは、RenderRepeater()メソッドを呼び出すときに自身のコピーを引き渡します。そのため、リストコントロールの個々の項目のレンダリングの際には、リストコントロール自身のRenderItem()メソッドが呼び出され、それによって適切な項目がレンダリングされます。つまり、CheckBoxListにはCheckBoxのインスタンス、RadioButtonListにはRadioButtonのインスタンスが追加されます。

DataListもお忘れなく
 ASP.NETに用意されている組み込みWebコントロールのうち、IRepeatInfoUserインターフェイスを実装しているものとしては、RadioButtonListとCheckBoxListの他にあと1つ、DataListがあります。このコントロールも、内部的にRepeatInfoクラスを使ってレンダリングを行います。前記2つがCheckBoxまたはRadioButtonをレンダリングするのに対し、DataListはDataListItemをレンダリングします。
 また、上の図では、RepeatInfoクラスが「適切な<table>セルをレンダリングする」(Render appropriate <table> cell)とあります。「適切な」という言葉を使ったのは、RepeatInfoクラスを使用するWebコントロールでは、1行当たりの項目数などのフォーマットオプションを、RepeatDirectionRepeatLayoutRepeatColumnsといったプロパティで指定できるためです。このプロパティをどう設定するかで、RepeatInfoクラスが当該項目のために表内に新しい行をレンダリングするかどうかが決まります。

 DropDownListとListBoxのレンダリングには、RepeatInfoクラスが使用されません。それぞれの項目は<option>要素として、RenderContents()メソッドの内部で直接レンダリングされます。具体的には、Itemsプロパティが列挙され、コレクション中のListItemごとに、<option>タグが適切なテキスト属性・値属性とともにレンダリングされます。DropDownListとListBoxとの違いは、ListBoxではレンダリングされる<select>タグにmultiple属性が加えられることです。これは、エンドユーザーがリストから複数の項目を選択できることを意味します。

リストコントロールのListItemには、なぜ属性を適用できないか

 リストコントロール中の項目に属性を与えようとして、ひどくがっかりした経験をお持ちの方は多いでしょう。たとえば、「Red」、「Green」、「Blue」の3項目を含むDropDownListを作成したいとします。どうせなら各項目の背景色をそれぞれ赤、緑、青にしたいと思い、次のようなコードを書いてみました。

'Assuming items in DropDownList are:
'Red, Green, and Blue (in that order)
DropDownListID.Items(0).Attributes("style") = "background-color:red;"
DropDownListID.Items(1).Attributes("style") = "background-color:green;"
DropDownListID.Items(2).Attributes("style") = "background-color:blue;"

 しかし、このページをブラウザに表示してみると、どのリスト項目の背景も白色になっているはずです。ソースを表示してみると、<option>要素にstyle属性が付加されていないことがわかります。宣言構文によって属性を指定した場合も同様で、属性は失われます。何が起こったのでしょう。

 残念ながら、リストコントロールでは項目属性をレンダリングできません。これは明らかにバグであり、ニュースグループ上でもさまざまに取り上げられています。リストコントロールのソースコードをReflectorで覗いてみると、「Attributes」と見れば、それをすべてオミットするように作られていることがわかります。この理由の一部は、おそらく、リストコントロールの各インスタンスが、レンダリング前はListItemクラスで表現されていることにあるのでしょう。AttributesコレクションはSystem.Web.UI.WebControls.WebControlクラスで定義されており、自動的にビューステートに保存されます。したがって、その値はポストバックが行われても存続します。一方、ListItemクラスはWebControlから派生したクラスではなく、Attributesプロパティを持っていますが、その値はビューステートに保存されません。

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
項目属性もレンダリングできるようにリストコントロールを拡張する

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Scott Mitchell(Scott Mitchell)

http://www.4guysfromrolla.com/ScottMitchell.shtml

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/230 2006/04/11 19:04

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング