■@Referenceディレクティブ
ただし、単にTransferメソッドを呼び出しただけでは、転送先であるページBから転送元であるページAのオブジェクトへアクセスすることはできない。このためには、ページAとページBの両方にいくつかの設定をしておく必要がある。
まずページA(Transferメソッドを呼び出す側)では、以下のように@PageディレクティブにClassName属性を追加して、暗黙的に宣言されるPageクラスのサブクラスに名前を付ける。ページBからは、この名前を通して、そのページ・クラスのオブジェクトへアクセスが行われる。なお、コード・ビハインドを利用してコーディングしている場合は、明示的にPageクラスのサブクラスが宣言されるため、ClassName属性は不要だ。とにかく、参照しやすいように意図した名前で宣言されていればよい。
<%@ Page Language="C#" ClassName="SourcePage" %>
……
次にページB側では、@Pageディレクティブに続けて@Referenceディレクティブを指定し、参照先となるページAのファイル名を指定する。
<%@ Page Language="C#" %>
<%@ Reference Page="sampleA.aspx" %>
……
以上のように、ページ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>
<%@ 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>
プログラムの実行結果は次のようになる。まずテキスト・ボックスに適当な文字列を入力する。
[検索]ボタンを押すと、ページは遷移して、入力された文字列にマッチするファイルがカレント・ディレクトリから検索され、一覧表示される。ページの遷移はサーバ内部で行われるため、IEの[アドレス]バーのURLは変化しない。
Copyright© Digital Advantage Corp. All Rights Reserved.