プログラマが、ASP.NET が自動生成する __doPostBack という名前の JavaScript 関数を、直接自分のコードに使ってはいけないという話です。
ASP.NET には、クライアントのイベントでサーバーにデータをポストバックするための、クライアントスクリプトを自動生成する機能があります。
それが表題の __doPostBack という名前の JavaScript の関数です。
例えば、GridView で、AutoGenerateSelectButton プロパティを true に設定すると[選択]ボタンが表示されますが、そのハイパーリンクに __doPostBack 関数が以下のように自動的に設定されます(ASP.NET 4 では ' はエスケープされて ' になります)。
<td>
<a href="javascript:__doPostBack('GridView1','Select$0')">
選択
</a>
</td>
引数は、前者がデータを受け取って処置をするサーバーコントロールの UniqueID(上の例では GridView1)、後者がイベントデータ(上の例では Select$0 ⇒ 行インデックス 0 が Select されたという意味)になります。
__doPostBack 関数は、この 2 つの引数をそれぞれ __EVENTTARGET と __EVENTARGUMENT という id を持つ隠しフィールドに格納してから form を submit します。
この __doPostBack 関数や隠しフィールドは公開されてないので、将来なにもアナウンスされず変更される可能性があります。なので、プログラマがこの関数や隠しフィールドを使ってコーディングするのは避けた方がよさそうです。
代わりに、GetPostBackEventReference メソッド と RaisePostBackEvent メソッド を使うのがお勧めです。
その例は、このブログの先の記事 CheckBox 付き Calendar コントロール でも紹介していますが、ここでも GridView を使って一例を紹介します。
上の画像は、GridView で[選択]ボタンを使わないで、行クリックでポストバックをかけ、SelectedIndexChanged イベントで選択された行を取得するサンプルです。__doPostBack 関数を直接使わないで、GetPostBackEventReference メソッドと RaisePostBackEvent メソッドを使って実現しています。
そのコードは以下の通りです。解説は、コードの中にコメントで書きましたので、そちらを参考にしてください。手抜きですみません。(笑)
実際に動かして試せるよう 実験室 にアップしましたので、興味のある方は試してみてください。
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
// GridView で[選択]ボタンを使わないでポストバックをかけて
// SelectedIndexChanged イベントで選択された行を取得。
// ASP.NET AJAX の UpdatePanel を使っているのはオマケ。
// 選択された行をチェックして SelectedIndexChanged イベント
// を発生させるため RaisePostBackEvent メソッドを override
// する。そのため GridView を継承したカスタムコントロールを
// 作る。
public class MyGridView : GridView
{
// GetPostBackEventReference メソッドで設定したクライアント
// スクリプト(この例では、下の myGridView_RowCreated イベ
// ントハンドラで設定している)が起動されると、ポストバッ
// クがかかり、サーバー側で RaisePostBackEvent メソッドが
// 起動される。引数 arg には、クライアントスクリプトで設定
// した GridView の行インデックスが渡される。
protected override void RaisePostBackEvent(string arg)
{
int index;
bool result = Int32.TryParse(arg, out index);
if (result)
{
if (this.SelectedIndex != index)
{
this.SelectedIndex = index;
this.OnSelectedIndexChanged(EventArgs.Empty);
}
}
base.RaisePostBackEvent(arg);
}
}
// データソース用の DataTable を作成
protected DataTable CreateDataTable()
{
DataTable dt = new DataTable();
DataRow dr;
dt.Columns.Add(new DataColumn("ID", typeof(Int32)));
dt.Columns.Add(new DataColumn("Name", typeof(string)));
dt.Columns.Add(new DataColumn("Price", typeof(Int32)));
dt.Columns.Add(new DataColumn("Qty", typeof(Int32)));
dt.Columns.Add(new DataColumn("Amount", typeof(Int32)));
dt.Columns.Add(new DataColumn("Remarks", typeof(string)));
for (int i = 0; i < 5; i++)
{
dr = dt.NewRow();
dr["ID"] = i;
dr["Name"] = "Item " + i.ToString();
dr["Price"] = 123000 * (i + 1);
dr["Qty"] = i + 1;
dr["Amount"] = 123000 * (i + 1) * (i + 1);
dr["Remarks"] = "Remarks " + i.ToString();
dt.Rows.Add(dr);
}
return dt;
}
protected void Page_Load(object sender, EventArgs e)
{
MyGridView myGridView = new MyGridView();
myGridView.ID = "myGridView1";
myGridView.RowCreated +=
new GridViewRowEventHandler(myGridView_RowCreated);
myGridView.SelectedIndexChanged +=
new EventHandler(myGridView_SelectedIndexChanged);
TableItemStyle tableStyle = myGridView.SelectedRowStyle;
tableStyle.BackColor = System.Drawing.Color.Blue;
tableStyle.ForeColor = System.Drawing.Color.White;
PlaceHolder1.Controls.Add(myGridView);
if (!IsPostBack)
{
myGridView.DataSource = CreateDataTable();
myGridView.DataBind();
}
}
protected void myGridView_RowCreated(
object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// __doPostBack("<UniqueID>", "<RowIndex>") という
// クライアントスクリプトの文字列が生成される。
string script =
Page.ClientScript.GetPostBackEventReference(
(GridView)sender,
e.Row.RowIndex.ToString());
// データ行の tr 要素の onclick 属性に、上で生成
// したスクリプトを設定する。
e.Row.Attributes["onclick"] = script;
// カーソルを指型にする
e.Row.Style["cursor"] = "pointer";
}
}
protected void myGridView_SelectedIndexChanged(
object sender, EventArgs e)
{
Label1.Text = "SelectedIndex: " +
((GridView)sender).SelectedIndex.ToString();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:PlaceHolder ID="PlaceHolder1"
runat="server">
</asp:PlaceHolder>
<asp:Label ID="Label1" runat="server">
</asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>