Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

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

データ連結式でaspxからコントロールツリーのデータを参照する

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

前回は、ASP.NETにおいてプレゼンテーションに依存する部分を、ITemplateの仕組みを用いてaspxに押し出す方法を解説しました。今回はそれを発展させて、aspxからControl Tree側のデータを参照する方法を解説します。

目次

はじめに

 前回は、ITemplateを用いてカスタムコントロールのプレゼンテーションをaspxに分離する方法を解説しました。

 しかし、前回までの解説では、プレゼンテーションに必要な値をすべてaspx内に記述することが前提となっています。これでは部分的に変わるコントロールの値をすべてコントロール側で実装する必要があり、ビューにかかわる知識を寄り多くコードに入れ込む必要があります。つまり、このままだと、プレゼンテーションとロジックを分離するという基本的な方針と合いません。

 今回は、逆にaspx内からコントロールのデータを参照する方法を解説します。

対象読者

 ASP.NETにおけるカスタムコントロールの作成を十分に理解し、前回の記事を読んでいて、Repeaterなどのコントロールでデータ連結式を用いたことがある方。

必要な環境

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

変更前のソリューションの説明

 Weatherは、次のように天気予報を表示するWebControlです。

変更前
変更前

 Weatherコントロールは、WeatherDataSouceから与えられる天気情報を元に、天気予報を表示します。WeatherDataSourceはただのダミー実装で、ここでの解説の主体ではありません。

 以後、本稿ではWeatherコントロールを変更していき、ロジックとプレゼンテーションの分離をしていきます。

 さっそく、変更前のWeatherコントロールを見てみましょう。

当初のaspx
<div>
    <MU:Weather runat="server" />
</div>
変更前CreateChildControls
protected override void CreateChildControls()
{
    Label day;
    Label weather;
    foreach (WeatherDataItem item in _dataSource.Weathers)
    {
        day = new Label();
        day.Text = item.Date.ToString("yyyy/MM/dd");
        weather = new Label();
        switch (item.Type)
        {
            case WeatherType.Sunney:
                weather.Text = "晴れ!";
                break;
            case WeatherType.Cloudy:
                weather.Text = "曇り!";
                break;
            case WeatherType.Rainy:
                weather.Text = "雨!";
                break;
        }
        Controls.Add(day);
        Controls.Add(new LiteralControl("<br>"));
        Controls.Add(weather);
        Controls.Add(new LiteralControl("<br><hr>"));
    }

}

 見て分かる通り、与えられたデータを元に日付と天気を表示しています。このコードには前回と同様、プレゼンテーションの部分とロジックがCreateChildControlsにすべて入ってしまっている、という問題があります。

目標とするaspx

 理想は、前に挙げたWeatherコントロールの表示に係わる所を、次のようにaspxに分離すべきでしょう。

理想とするのaspx
<div>
    <MU:Weather runat="server">
        <Template>
            (日付)<br>
            (天気)<br><hr>
        </Template>
    </MU:Weather>
</div>

 ここで問題があります。上記、「(日付)」の部分と「(天気)」の部分をどうaspxで記述したら良いのでしょうか? この値は、WeatherDataSourceからくる値です。

 結論から言うと、テンプレート内でデータを展開する手段がASP.NETでは用意されていて、それを使うことになります。その手段が、実は皆さんが普段使っているデータ連結式、つまり<%#で始まり%>で終わる文です。それを用いると、次のような記述になります。

データ連結式を用いたaspx
<div>
    <MU:Weather runat="server">
        <Template>
            <%# Container.FormatedDate %><br>
            <%# Container.FormatedWeatherType %><br><hr>
        </Template>
    </MU:Weather>
</div>

 これはASP.NETでよく見られる、Repeaterコントロールと同じ物です。

 以下、これを実現するためのデータ連結式を解説してきます。

テンプレート化

 ここでは、以下に示すようなコントロールツリーになるように、コーディングを進めます。

 この各WeatherDayContainerがちょうど前回のCheckTextに相当します。

 それでは前回のコードを参考に、このツリーを作ってみましょう。まずはWeatherDayContainerを作ります。

WeatherDayContainer
public class WeatherDayContainer : WebControl, INamingContainer
{
}

 これはテンプレートが下に展開されるだけのコントロールなので、中身は殻にしておきます。INamingContainerについては、後ほど解説します。

 次に前回の記事にならい、ITemplateを受け取る部分を作ります。

ITemplateを受け取る
private ITemplate _dayTemplate;

[TemplateContainer(typeof(WeatherDayContainer))]
public ITemplate DayTemplate
{
    set { _dayTemplate = value; }
}

 これで_dayTemplateにITemplateがセットされるのは前回解説しました。最後にCreateChildControlsで、これを使うように変更します。

テンプレート化したCreateChildControls
protected override void CreateChildControls()
{
    foreach (WeatherDataItem item in _dataSource.Weathers)
    {
        WeatherDayContainer container = new WeatherDayContainer();
        _dayTemplate.InstantiateIn(container);
        Controls.Add(container);
    }
}

 あとは、aspx側にテンプレートを記述します。

 ここでは、前回までの知識で分かるようにデータ連結式は使わず、暫定的にいつも同じテキストを表示するようにします。

テンプレート化したaspx
<MU:Weather runat="server">
    <DayTemplate>
        毎日晴れ<br />
    </DayTemplate>
</MU:Weather>

 これにより、「毎日晴れ」が4回表示されます。

毎日晴れ
毎日晴れ

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

著者プロフィール

  • mumurik(ムムリク)

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

バックナンバー

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