Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

ITemplateでコントロールのプレゼンテーションを分離する(前編)

見た目の変更に柔軟に対応できるカスタムコントロールの作成

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2006/06/28 00:00

ダウンロード 変更前 (2.4 KB)
ダウンロード 変更後 (2.7 KB)

ASP.NETでカスタムの複合コントロールを作る際、コードの中にプレゼンテーションに依存する部分を入れてしまうと、見た目を変更したい時に毎回コードの変更が必要になってしまい、保守が困難です。そこで本稿では、カスタムコントロールのプレゼンテーションを、ITemplateを用いて分離する方法を解説します。

完成図
完成図

はじめに

 ASP.NETでカスタムの複合コントロールを作る場合、通常はCreateChildControlで子供のコントロールを自身にぶらさげていきます。

 しかし、C#のコードの中にプレゼンテーションに依存する部分を入れてしまうと、見た目を変更したい時に毎回コードの変更が必要になってしまい、保守が困難です。

 この問題を解決するために、ASP.NETにはカスタムコントロールのプレゼンテーションを分離する、ITemplateという仕組みがあります。

 本稿では、チェックボックスとテキストボックスが連携するカスタムコントロールをITemplate化することで、この仕組みを見ていきます。

対象読者

 ASP.NETでカスタムコントロールの作成を十分に理解している方。

必要な環境

 Microsoft Visual Web Developer 2005で確認しています。ASP.NET 1.0以降の環境なら、配置の変更だけで対応できるはずです。

変更前のソリューション構成

変更前
変更前

 このように、「App_Code」下にCheckTextというカスタムコントロールがあります。

 このコントロールはチェックボックスとテキストボックスを持ち、チェックボックスがチェックされるとテキストボックスのenable/disableがトグルします。

 このコードは、以下に示すようにレイアウトに関することがハードコードされてしまっています。

CreateChildControls 変更前
protected override void CreateChildControls()
{
    _box = new CheckBox();
    _text = new TextBox();
    _box.AutoPostBack = true;
    _text.Enabled = false;
    _box.CheckedChanged += new EventHandler(box_CheckedChanged);
    Controls.Add(_box);
    Controls.Add(_text);
}

 これは、カスタムコントロールでなければ、aspx側に次のように記述すべき内容です。

本来のレイアウト
<asp:CheckBox ID="checkBox" runat="server" AutoPostBack="true" />
<asp:TextBox ID="textBox" runat="server" Enabled="false" />

 このようになっていれば、チェックボックスをテーブルに入れたり、スタイルを当てたりと、自由に扱うことができますが、現状のつくりではCreateChildControlsを変更して、読みづらいコードを書かなくてはなりません。

ITemplate化に必要な作業(aspx側)

 それではITemplate化に必要な作業を見ましょう。

変更後のaspx
<MU:CheckText runat="server">
    <Template>
       <asp:CheckBox ID="checkBox" runat="server" AutoPostBack="true" />
       <asp:TextBox ID="textBox" runat="server" Enabled="false" />
    </Template>
</MU:CheckText>

 CheckTextの中に好きなタグ(この場合は「Template」という名前のタグ)を作り、その内部に通常のaspxのようにタグを記述します。

 こうしておくと、ASP.NETは自動生成したITemplateというものをCheckTextコントロールの同名のプロパティ(つまりTemplate)にセットしてくれます。

 また、C#側からCheckBoxTextBoxが取得できるように、IDをふっておきます。

ITemplate化に必要な作業(cs側)

 aspx側に合わせてcs側も変更します。

 まずはクラス定義にINamingContainerを追加します。

クラス定義 変更後
public class CheckText : WebControl, INamingContainer

 次にaspxで決めたタグ名(今回はTemplate)に対応するITemplate型のpublic propertyを定義します。

ITemplateプロパティ定義
private ITemplate _template;

[TemplateContainer(typeof(CheckText))]
public ITemplate Template
{
    set { _template = value; }
}

 TemplateContainerは自分自身のクラス名を指定します。このセッタがASP.NETから呼ばれます。何をするかは自由ですが、ここでは_templateというローカル変数に代入することにしましょう。

 後はCreateChildControlsを次のように書き直します。

CreateChildControls 変更後
protected override void CreateChildControls()
{
    _template.InstantiateIn(this);
    _box = (CheckBox) FindControl("checkBox");
    _text = (TextBox) FindControl("textBox");
    _box.CheckedChanged += new EventHandler(box_CheckedChanged);
}

 このように、_template.InstantiateIn(this)を呼ぶと、aspx側に記述されたコントロールがthisの下に展開されます。

 そこから先は通常のControls.Add()と同様にFindControlで取得することができます。

プレゼンテーションを変更してみる

 それではせっかくテンプレート化したので、表示を変更してみましょう。

 元のページは次のような物です。

変更前のページ
変更前のページ

 これをtableでレイアウトしましょう。これは、aspxを次のように変更するだけで行うことができます。

変更後のaspx
<MU:CheckText runat="server">
  <Template>
    <table border="1">
      <tr>
        <td>check!</td>
        <td>
          <asp:CheckBox ID="checkBox" runat="server" AutoPostBack="true" />
        </td>
      </tr>
      <tr>
        <td colspan="2">
          <asp:TextBox ID="textBox" runat="server" Enabled="false" />
        </td>
      </tr>
    </table>
  </Template>
</MU:CheckText>

 変更後は次のように表示されます。プレゼンテーションとロジックが分離されているのが分かると思います。

変更後ページ
変更後ページ

まとめ

 ITemplateを使用することでコントロールのプレゼンテーションを分離することができます。プレゼンテーションをクライアントに任せることにより、通常のコントロールよりも保守性と再利用性を高める事ができます。

 後編では、今回解説をせずに導入したTemplateContainerアトリビュートとINamingContainerについて解説します。TemplateContainerの理解はカスタムコントロールに限らず、既存のASP.NETコントロールであるRepeaterクラスやDataGridクラスを真に理解するのにも欠かせません。ご期待ください。



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

著者プロフィール

  • mumurik(ムムリク)

    最近の本業はASP.NET上でのパッケージアプリケーション開発。 WebControlとjsのコードが半分づつくらい。

バックナンバー

連載:ITemplateでコントロールのプレゼンテーションを分離する
All contents copyright © 2005-2019 Shoeisha Co., Ltd. All rights reserved. ver.1.5