第16回 ASP.NETにおけるページの遷移連載 プログラミングASP.NET ―ASP.NETによるWebアプリケーション実践開発講座― (2/4 ページ)

» 2003年04月05日 00時00分 公開
[田口景介]

 

■@Referenceディレクティブ

 ただし、単にTransferメソッドを呼び出しただけでは、転送先であるページBから転送元であるページAのオブジェクトへアクセスすることはできない。このためには、ページAとページBの両方にいくつかの設定をしておく必要がある。

 まずページA(Transferメソッドを呼び出す側)では、以下のように@PageディレクティブにClassName属性を追加して、暗黙的に宣言されるPageクラスのサブクラスに名前を付ける。ページBからは、この名前を通して、そのページ・クラスのオブジェクトへアクセスが行われる。なお、コード・ビハインドを利用してコーディングしている場合は、明示的にPageクラスのサブクラスが宣言されるため、ClassName属性は不要だ。とにかく、参照しやすいように意図した名前で宣言されていればよい。

<%@ Page Language="C#" ClassName="SourcePage" %>
……

ページA(sampleA.aspx)に必要な@Pageディレクティブ

 次にページB側では、@Pageディレクティブに続けて@Referenceディレクティブを指定し、参照先となるページAのファイル名を指定する。

<%@ Page Language="C#" %>
<%@ Reference Page="sampleA.aspx" %>
……

ページB(sampleB.aspx)に必要な@Pageディレクティブと@Referenceディレクティブ

 以上のように、ページAとページBの両方にディレクティブの設定を行えば、次に示すコードで、ページBからページAのページ・オブジェクトへとアクセスできるようになる。

void Page_Load(object sender, EventArgs e) {
  if (!IsPostBack) {
    if (Context.Handler is SourcePage) {
      SourcePage sp = (SourcePage)Context.Handler;
      l.Text = sp.arg;
    } else {
      l.Text = Context.Handler.ToString();
    }
  }
}

遷移元のページへアクセスするコード

 ここでポイントとなるのが、Context.Handlerプロパティである。Transferメソッドによってこのページへ移ってきた場合、このプロパティにはページAのページ・オブジェクト、つまりClassName属性により名前を付けたSourcePageオブジェクトが格納されている。そこで、これをSourcePageクラスにキャストすれば、あたかもページA上にいるかのごとく、SourcePageオブジェクトを通してページAのフィールドやプロパティ、メソッドにアクセスできるようになる(ただしpublicメンバのみ)。上記のコードでは、ページAで宣言されているargフィールドを通して、テキスト・ボックスに入力された文字列を取得している。

 ただし、Transferメソッドを使わず、直接このページがアクセスされたとき、Context.Handlerにはこのページ自身のページ・オブジェクトが格納されているため、SourcePageクラスへのキャストは失敗する。そこで、キャストする前にis演算子を使って、Context.HandlerがSourcePageオブジェクトであるか確かめておく必要がある。また、Transferメソッドによって移ってきたときは、「IsPostBack == false」が成立する状態であることにも注意すること。

 このテクニックを使ったサンプル・プログラムをリスト16.2リスト16.3に示す。フォームに入力された文字列にマッチするファイルをカレント・ディレクトリから検索し、一覧表示するプログラムである。このサンプル・プログラムはsample01a.aspxとsample01b.aspxから構成され、sample01a.aspxからポストバックされた後、Transferメソッドによって遷移されたsample01b.aspxからレスポンスが行われる。その結果、レスポンスにはフォームが含まれず、結果だけが表示される。

<%@ Page Language="C#" ClassName="SourcePage" %>
<html>
<head>
<script runat="server">
public string arg;

void Page_Load(object sender, EventArgs e) {
  if (IsPostBack) {
    arg = t.Text;
    Server.Transfer("sample01b.aspx");
  }
}
</script>
</head>
<body>
<form runat="server">
  <asp:TextBox id="t" runat="server" />
  <asp:Button Text="検索" runat="server" />
</form>
</body>
</html>

リスト16.2 別ページへのポスト(sample01a.aspx)

<%@ Page Language="C#" %>
<%@ Reference Page="sample03a.aspx" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Data" %>
<html>
<head>
<script runat="server">
SourcePage sp;

void Page_Load(object sender, EventArgs e) {
  if (!IsPostBack) {
    if (Context.Handler is SourcePage) {
      sp = (SourcePage) Context.Handler;
      datagrid.DataSource = CreateDataSource(sp.arg);
      datagrid.DataBind();
    } else {
      datagrid.DataSource = CreateDataSource("");
      datagrid.DataBind();
    }
  }
}

ICollection CreateDataSource(string s) {
  DirectoryInfo di = new DirectoryInfo(Server.MapPath("."));
  FileInfo[] fi = di.GetFiles();

  DataTable dt = new DataTable();
  DataRow dr;

  dt.Columns.Add(new DataColumn("fileid", typeof(int)));
  dt.Columns.Add(new DataColumn("filename", typeof(String)));
  dt.Columns.Add(new DataColumn("filesize", typeof(long)));
  dt.Columns.Add(new DataColumn("date", typeof(DateTime)));

  for (int i = 0; i < fi.Length; i++) {
    dr = dt.NewRow();
    dr[0] = i;
    dr[1] = fi[i].Name;
    dr[2] = fi[i].Length;
    dr[3] = fi[i].LastWriteTime;
    dt.Rows.Add(dr);
  }

  DataView dv = new DataView(dt);
  dv.RowFilter = "filename LIKE '*" + s + "*'";

  return dv;
}

</script>
</head>
<body>
  <asp:DataGrid id="datagrid" Width="90%" runat="server" />
</body>
</html>

リスト16.3 別ページへのポスト(sample01b.aspx)
sample01a.aspxとsample01b.aspxのダウンロード(sample01.zip)

 プログラムの実行結果は次のようになる。まずテキスト・ボックスに適当な文字列を入力する。

図16.3 sample01a.aspxの実行結果
sample01a.aspxの実行(www.iwebmethod.netのページ)

 [検索]ボタンを押すと、ページは遷移して、入力された文字列にマッチするファイルがカレント・ディレクトリから検索され、一覧表示される。ページの遷移はサーバ内部で行われるため、IEの[アドレス]バーのURLは変化しない。

図16.4 sample01b.aspxの実行結果

  

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。