.NET TIPS

[ASP.NET]1つのWebフォーム内で一覧/詳細画面を切り替えるには?

山田 祥寛
2005/09/23

 Webアプリケーションを構築していると、検索結果などをサマライズする一覧画面と、より詳細なデータを表示する詳細画面が必要となる局面が多い。このような場合に、従来、どのように対処していただろうか。

 DataGridコントロールのSelectedIndexChangedイベントを利用して選択行のキー情報を取得し、これをクエリ情報として付加したうえで、Server.Transferメソッドで詳細画面にリダイレクトするという方法を採っていた方も多いかもしれない(SelectedIndexChangedイベントの詳細については、「TIPS:[ASP.NET]DataGridコントロールに選択ボタンを追加するには?」を参照)。例えば、以下のようにだ。

Sub grid_Changed(sender As Object, e As EventArgs)
  Server.Transfer("description.aspx?id=" & grid.SelectedItem.Cells(0).Text)
End Sub

 しかし、このようなコードはいったん自分自身にポストバックしなければならないという意味で直截(ちょくさい)的でないし、ソートやページング機能を伴うグリッドでは、ページを切り替えることで、ページの状態が初期に戻ってしまうのもうれしくない。

PlaceHolderコントロールを用いた一覧/詳細画面の切り替え

 そこで本稿では、ASP.NETのPlaceHolderコントロールを利用して、一覧画面と詳細画面を1つのWebフォーム内で管理する方法を紹介する。PlaceHolderコントロールを利用することで、一覧/詳細画面の切り替えをより直感的なコードで記述できるようになり、グリッドの状態保持を開発者が意識する必要もなくなる。

 なお、本稿のサンプルを実行するに当たっては、あらかじめデータベース上に以下のようなレイアウトを持つbooksテーブルを作成しておく必要がある。

フィールド名 データ型 概要
isbn VARCHAR(255) ISBNコード(主キー)
title VARCHAR(255) 書名
price INT 価格
publish VARCHAR(255) 出版社
puslished DATETIME 出版日
booksテーブルのフィールド・レイアウト

 それではさっそく、具体的なコードを見てみることにしよう。

<%@ Page ContentType="text/html" Language="C#" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script runat="Server">

Hashtable table = null;
SqlDataReader reader = null;

void Page_Load(Object sender, EventArgs e) {
  if (!Page.IsPostBack) {

    // booksテーブルからpublishedフィールド昇順にデータを取得
    SqlConnection db = new SqlConnection("Data Source=(local);User ID=sa;Password=sa;Persist Security Info=True;Initial Catalog=dotnet");
    SqlCommand comm = new SqlCommand("SELECT isbn,title,publish FROM books ORDER BY published DESC", db);
    db.Open();

    // 取得したDataReaderオブジェクトを
    // DataGridコントロールにバインド
    reader = comm.ExecuteReader();
    grid.DataBind();
    db.Close();
  }
}

// グリッドの選択行が変更されたタイミングで実行
void grid_Changed(Object sender, EventArgs e) {
  SqlConnection db = new SqlConnection("Data Source=(local);User ID=sa;Password=sa;Persist Security Info=True;Initial Catalog=dotnet");

  // 選択された行のISBNコードをキーにbooksテーブルを検索
  SqlCommand comm = new SqlCommand("SELECT isbn,title,price,publish,published FROM books WHERE isbn=@isbn", db);
  comm.Parameters.Add("@isbn", grid.SelectedItem.Cells[0].Text);
  db.Open();
  SqlDataReader reader_desc = comm.ExecuteReader();

  // 取得したDataReaderオブジェクトの内容を
  // Labelコントロールに反映
  if (reader_desc.Read()) {
    isbn.Text = reader_desc.GetString(0);
    title.Text = reader_desc.GetString(1);
    price.Text = reader_desc.GetInt32(2).ToString("#,#00円");
    publish.Text = reader_desc.GetString(3);
    published.Text =
      reader_desc.GetDateTime(4).ToString("yyyy年MM月dd日");
  }
  db.Close();

  // 一覧ビューを不可視、詳細ビューを可視状態に、それぞれ変更
  listPlace.Visible = false;
  descPlace.Visible = true;
}
void link_Click(Object sender, EventArgs e){
  // 一覧ビューを可視、詳細ビューを不可視状態に、それぞれ変更
  listPlace.Visible = true;
  descPlace.Visible = false;
}
</script>
<html>
<head>
<title>PlaceHolderコントロールによる一覧/詳細画面の切り替え</title>
</head>
<body>
<form runat="Server">

<asp:PlaceHolder id="listPlace" runat="Server" Visible="True">
  <asp:DataGrid id="grid" runat="Server" DataSource="<%# reader %>"
    DataKeyField="isbn" AutoGenerateColumns="False"
    OnSelectedIndexChanged="grid_Changed">
    <HeaderStyle BackColor="#BB2255" ForeColor="white" />
    <ItemStyle BackColor="#FFeeEE" />
    <AlternatingItemStyle BackColor="#FFDDDD" />
    <Columns>
      <asp:BoundColumn DataField="isbn" HeaderText="ISBNコード" />
      <asp:BoundColumn DataField="title" HeaderText="書名" />
      <asp:BoundColumn DataField="publish" HeaderText="出版社" />
      <asp:ButtonColumn HeaderText="" ButtonType="PushButton"
        CommandName="Select" Text="詳細" />
    </Columns>
  </asp:DataGrid>
</asp:PlaceHolder>

<asp:PlaceHolder id="descPlace" runat="Server" Visible="False">
<table cellspacing="0" cellpadding="2" rules="all" border="1"
  style="border-collapse:collapse;">
  <tr>
    <th align="right" bgcolor="#FFDDDD">ISBNコード</td>
    <td align="left" bgcolor="#FFEEEE">
      <asp:Label id="isbn" runat="Server" />
    </td>
  </tr><tr>
    <th align="right" bgcolor="#FFDDDD">書名</td>
    <td align="left" bgcolor="#FFEEEE">
      <asp:Label id="title" runat="Server" /></td>
  </tr><tr>
    <th align="right" bgcolor="#FFDDDD">価格</td>
    <td align="left" bgcolor="#FFEEEE">
      <asp:Label id="price" runat="Server" /></td>
  </tr><tr>
    <th align="right" bgcolor="#FFDDDD">出版社</td>
    <td align="left" bgcolor="#FFEEEE">
      <asp:Label id="publish" runat="Server" /></td>
  </tr><tr>
    <th align="right" bgcolor="#FFDDDD">配本日</td>
    <td align="left" bgcolor="#FFEEEE">
      <asp:Label id="published" runat="Server" /></td>
  </tr>
</table>
[<asp:LinkButton id="link" runat="Server"
  Text="一覧へ" OnClick="link_Click" />]
</asp:PlaceHolder>

</form>
</body>
</html>
一覧/詳細画面を切り替えるためのWebフォーム(C#版:multi_cs.aspx)
 
<%@ Page ContentType="text/html" Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script runat="Server">

Dim table As Hashtable
Dim reader As SqlDataReader

Sub Page_Load(sender As Object, e As EventArgs)
  If Not Page.IsPostBack Then

    ' booksテーブルからpublishedフィールド昇順にデータを取得
    Dim db As New SqlConnection("Data Source=(local);User ID=sa;Password=sa;Persist Security Info=True;Initial Catalog=dotnet")
    Dim comm As New SqlCommand("SELECT isbn,title,publish FROM books ORDER BY published DESC", db)
    db.Open()

    ' 取得したDataReaderオブジェクトを
    ' DataGridコントロールにバインド
    reader = comm.ExecuteReader()
    grid.DataBind()
    db.Close()
  End If
End Sub

' グリッドの選択行が変更されたタイミングで実行
Sub grid_Changed(sender As Object, e As EventArgs)
  Dim db As New SqlConnection("Data Source=(local);User ID=sa;Password=sa;Persist Security Info=True;Initial Catalog=dotnet")

  ' 選択された行のISBNコードをキーにbooksテーブルを検索
  Dim comm As New SqlCommand("SELECT isbn,title,price,publish,published FROM books WHERE isbn=@isbn", db)
  comm.Parameters.Add("@isbn", grid.SelectedItem.Cells(0).Text)
  db.Open()
  Dim reader_desc As SqlDataReader = comm.ExecuteReader()

  ' 取得したDataReaderオブジェクトの内容を
  ' Labelコントロールに反映
  If reader_desc.Read() Then
    isbn.Text = reader_desc.GetString(0)
    title.Text = reader_desc.GetString(1)
    price.Text = reader_desc.GetInt32(2).ToString("#,#00円")
    publish.Text = reader_desc.GetString(3)
    published.Text = _
      reader_desc.GetDateTime(4).ToString("yyyy年MM月dd日")
  End If
  db.Close()

  ' 一覧ビューを不可視、詳細ビューを可視状態に、それぞれ変更
  listPlace.Visible = False
  descPlace.Visible = True
End Sub

Sub link_Click(sender As Object, e As EventArgs)
  ' 一覧ビューを可視、詳細ビューを不可視状態に、それぞれ変更
  listPlace.Visible = True
  descPlace.Visible = False
End Sub
</script>
<html>
<head>
<title>PlaceHolderコントロールによる一覧/詳細画面の切り替え</title>
</head>
<body>
<form runat="Server">

<asp:PlaceHolder id="listPlace" runat="Server" Visible="True">
  <asp:DataGrid id="grid" runat="Server" DataSource="<%# reader %>"
    DataKeyField="isbn" AutoGenerateColumns="False"
    OnSelectedIndexChanged="grid_Changed">
    <HeaderStyle BackColor="#BB2255" ForeColor="white" />
    <ItemStyle BackColor="#FFeeEE" />
    <AlternatingItemStyle BackColor="#FFDDDD" />
    <Columns>
      <asp:BoundColumn DataField="isbn" HeaderText="ISBNコード" />
      <asp:BoundColumn DataField="title" HeaderText="書名" />
      <asp:BoundColumn DataField="publish" HeaderText="出版社" />
      <asp:ButtonColumn HeaderText="" ButtonType="PushButton"
        CommandName="Select" Text="詳細" />
    </Columns>
  </asp:DataGrid>
</asp:PlaceHolder>

<asp:PlaceHolder id="descPlace" runat="Server" Visible="False">
<table cellspacing="0" cellpadding="2" rules="all" border="1"
  style="border-collapse:collapse;">
  <tr>
    <th align="right" bgcolor="#FFDDDD">ISBNコード</td>
    <td align="left" bgcolor="#FFEEEE">
      <asp:Label id="isbn" runat="Server" />
    </td>
  </tr><tr>
    <th align="right" bgcolor="#FFDDDD">書名</td>
    <td align="left" bgcolor="#FFEEEE">
      <asp:Label id="title" runat="Server" /></td>
  </tr><tr>
    <th align="right" bgcolor="#FFDDDD">価格</td>
    <td align="left" bgcolor="#FFEEEE">
      <asp:Label id="price" runat="Server" /></td>
  </tr><tr>
    <th align="right" bgcolor="#FFDDDD">出版社</td>
    <td align="left" bgcolor="#FFEEEE">
      <asp:Label id="publish" runat="Server" /></td>
  </tr><tr>
    <th align="right" bgcolor="#FFDDDD">配本日</td>
    <td align="left" bgcolor="#FFEEEE">
      <asp:Label id="published" runat="Server" /></td>
  </tr>
</table>
[<asp:LinkButton id="link" runat="Server"
  Text="一覧へ" OnClick="link_Click" />]
</asp:PlaceHolder>

</form>
</body>
</html>
一覧/詳細画面を切り替えるためのWebフォーム(VB.NET版:multi_vb.aspx)

 PlaceHolderコントロールは、その名のとおり、Webフォーム内のコントロールの置き場所(プレイスホルダ)を確保するためのコントロールだ。アプリケーションから動的にコントロールを追加する場合や、今回のように配下のコンテンツの可視/不可視をまとめて切り替えたい場合などに利用することができる。

 これによく似たサーバ・コントロールとしてPanelコントロールがあるが、こちらがWebControlクラス(System.Web.UI.WebControls名前空間)を継承するのに対して、PlaceHolderコントロールはControlクラス(System.Web.UI名前空間)を継承している。

 つまり、背景色や境界線、フォントなどのスタイル属性そのほか、サーバ・コントロール共通で利用可能な属性を使いたい場合には、Panelコントロールを使用する必要がある。本稿のように、単なるコントロールのプレイスホルダとして利用したい場合には、PlaceHolderコントロールを利用すればよいだろう。

 コード内のコメントを参照していただければ分かるように、PlaceHolderコントロールの可視/不可視はVisibleプロパティを設定するだけで変更できる。このため一覧/詳細画面の切り替えには、DataGridコントロールのSelectedIndexChangedイベント、もしくはHyperLinkコントロールのClickイベントが発生したタイミングで、あらかじめ用意しておいた一覧/詳細のビューのVisibleプロパティを反転させればよい。

 以上を理解できたら、さっそく、サンプル・プログラムを起動してみよう。以下のようにグリッド上の[詳細]ボタン、または詳細画面の[一覧へ]リンクをクリックすることで、一覧/詳細画面が切り替わることが確認できれば成功だ。


サンプル・アプリケーションの実行結果
グリッド上の[詳細]ボタン、または詳細画面の[一覧へ]リンクをクリックすることで、一覧画面(上)と詳細画面(下)が切り替わる。

 なお、ASP.NET 2.0ではMultiViewコントロールを利用することで、同等の処理がよりスマートに実現できるようになる。MultiViewコントロールについては、「ASP.NET 2.0のログイン管理とウィザード・ページ」を参照していただきたい。End of Article

カテゴリ:Webフォーム 処理対象:PlaceHolderコントロール
使用ライブラリ:PlaceHolderコントロール
関連TIPS:[ASP.NET]DataGridコントロールに選択ボタンを追加するには?
 
この記事と関連性の高い別の.NET TIPS
[ASP.NET]MultiView/Viewコントロールでマルチビューのページを作成するには?
[ASP.NET]GridView+DetailsViewコントロールで一覧/明細画面を作成するには?
[ASP.NET AJAX]AlwaysVisibleControlコントロールで常時表示されるパネルを定義するには?
[ASP.NET AJAX]PopupControlコントロールで標準コントロールにポップアップ機能を追加するには?
[ASP.NET]DataGridコントロールのページ移動ボタンをカスタマイズするには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム 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 記事ランキング

本日 月間