はじめに
Webアプリケーションの世界では、「Ajax」と呼ばれる再読み込みを行わずに画面上の表示を書き換える技術が注目されています。この流れに合わせるように、ASP.NET 2.0で提供されているGridViewコントロールには、再読み込みを行わずにデータの表示ページを切り換える設定(EnableSortingAndPagingCallbacks
プロパティ)が用意されています。
ただし、このプロパティをtrueに設定して利用する場合には、TemplateFieldや選択ボタンが使えないという制限があります。ここでは、その制限の中でGridViewを利用するためにどうしたらよいかを考えてみましょう。
対象読者
ASP.NETでWebアプリケーションを開発している方。
必要な環境
GridViewの動きを確認する
まずGridViewのEnableSortingAndPagingCallbacks
プロパティをtrueに設定した場合の動作を確認してみましょう。最初にGridViewに表示するテーブルを以下の内容で作成します。このテーブルにはテスト用のデータを数件入力しておきます。
項目1 | userID | int | 主キー |
項目2 | userName | nvarchar(50) | Nullを不許可 |
項目3 | nvarchar(50) | Nullを許可 |
画面上には再読み込みが発生したかどうかを確認するために、時刻を表示するためのラベルと、上記のテーブルをドラッグ&ドロップして作成したGridViewを貼り付けます。GridViewは「ページング」「編集」「削除」を有効にし、EnableSortingAndPagingCallbacks
プロパティを「true」に設定しておきます。
コードを表示し、Page_Load
メソッドに以下のように入力して、画面が作成された時刻が表示されるようにします。
protected void Page_Load(object sender, EventArgs e) { this.Label1.Text = DateTime.Now.ToString(); }
デバッグを実行し、動作を確認してみましょう。ページを変更しても画面上の時刻は変わらないことが、以下の2つの図を比較すると確認できます。
このとき、[編集]や[削除]をクリックすると画面上の時刻が変わります。ここから、これらの作業を実行する際には、サーバへのPostBackが行われていることが分かります。
データの削除を確認できるようにする
デバッグ時に[削除]をクリックすると、ただちにデータの削除が行われてしまいます。これではオペレーションのミスで重要なデータが消えてしまうことになりかねません。削除するかどうかを確認するメッセージを表示するようにしましょう。
[削除]をクリックしたときにメッセージを表示させるには、[削除]リンクボタンのOnClientClick
プロパティにJavaScriptを追加します。ただし、[削除]リンクボタンはCommandFieldによって実行時に生成されて表示されているリンクボタンなので、デザイン画面からプロパティの設定を行うことができません。TemplateFieldが使えるのであれば、CommandFieldをTemplateFieldに変換したうえで[削除]リンクボタンのプロパティを設定するという方法が使えるのですが、EnableSortingAndPagingCallbacks
をtrueにした状態では、これはエラーになってしまいます。そこで、実行時にプログラムからプロパティの設定を行うことにします。
[削除]リンクボタン生成のしくみ
まず、ターゲットとなる[削除]リンクボタンがどのように生成されているかを確認してみましょう。このためにページのTraceを有効にします。「プロパティ」ウィンドウで[DOCUMENT]を選択し、Trace
プロパティを「true」に設定します。
これはPageディレクティブにTrace="true"
という記述を追加するのと同じ意味を持ちます。
この状態でデバッグを実行してみましょう。「要求の詳細」「トレース情報」「コントロールのツリー」など、さまざまな情報が表示されますが、ここでは「コントロールのツリー」の中に注目します。
GridViewには1つのChildTableが含まれており、ChildTableには以下の6つのGridViewRowが含まれています。
- ヘッダー行
- データ行(3行)
- フッター行(非表示)
- ページコントロール行
そしてデータ行の先頭にはDataControlFieldCellがあり、そこに以下の3つのコントロールが存在しています。
- DataControlLinkButton([編集]リンクボタン)
- LiteralControl(半角空白)
- DataControlLinkButton([削除]リンクボタン)
[削除]リンクボタンの実体であるDataControlLinkButtonですが、ドキュメントには説明がありません。しかし、名前とその動作からLinkButtonコントロールから派生したコントロールではないかと推測できます。
プロパティを操作するプログラム
さて、[削除]リンクボタンがどこでどのように生成されているかが分かったところで、そのプロパティを操作するプログラムを記述することにしましょう。このとき、プロパティを操作するタイミングをどのイベントが発生したときにするかを考える必要があります。ここではGridViewにデータが連結(バインド)されたときに発生するRowDataBoundイベントの中でプロパティを操作することにします。
GridViewの「プロパティ」ウィンドウで、稲妻型のアイコンをクリックしてイベントの一覧を表示し、RowDataBoundイベントをダブルクリックします。GridView1_RowDataBound
メソッドが生成されるので、そこに以下のように記述します。
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) ((LinkButton)e.Row.Cells[0].Controls[2]).OnClientClick = "return confirm('削除してよろしいですか');"; }
このプログラムでは、最初に今操作している行がデータ行かどうかを判定します。そしてデータ行だったら、最初のセル(Cells[0]:DataControlFieldCell
)の中の3番目のコントロール(Controls[2]:DataControlLinkButton
)を取り出し、そのコントロールをLinkButtonにキャストしてOnClientClick
プロパティにJavaScript(文字列)を設定します。
これでデバッグを開始してみましょう。推測通り、DataControlLinkButtonはLinkButtonから派生したコントロールだったようで、キャストによるエラーはありません。表示される画面上で[削除]をクリックすると、以下の確認画面が表示されます。
さて、ここで[編集]をクリックしてデータの編集モードを表示し、[キャンセル]をクリックしてみましょう。すると、[削除]をクリックしたときと同じように確認画面(図6)が表示されてしまいます。これは、データ行の最初のセルにある3番目のコントロールのOnClientClick
プロパティに、常にJavaScriptを設定してしまっているからです。
データ行が編集モードのときにはJavaScriptを設定しないよう、GridView1_RowDataBound
メソッドを次のように修正しておきましょう。
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) if (e.Row.RowIndex != GridView1.EditIndex) // この条件文を追加 ((LinkButton)e.Row.Cells[0].Controls[2]).OnClientClick = "return confirm('削除してよろしいですか');"; }