by WebSurfer
2015年7月7日 16:14
GridView と SqlDataSource を使用してページングを行う際、最終ページの行数が PageSize より少ない場合、最終データ行の次に即ページャー行が表示されます。(下の画像のように空行は表示されません)
それを、上の画像のように空行を挿入(例えば、PageSize が 10 で、最終ページのデータ行が 7 行の場合、空のデータ行を 3 行追加する)する方法を書きます。
自力でコードを書いて DataTable を作って、それを GridView にデータバインドしているような場合は、DataTable に空行を追加するのが簡単そうですが、GridView と SqlDataSource を組み合わせて使っているような場合はその手が使えません。(ウラワザ的なことをすれば話は別かもしれませんが)
なので、DataTable を細工するのは諦めて、GridView.RowCreated イベントでデータ行の行数を調べ、それが PageSize より少ない場合は空の GridViewRow を追加する方法を取ってみました。
簡単に書くと、(1) ヘッダ行で RowCreated イベントが発生した際にそのセル数を取得。[ヘッダ行のセル数] = [データ行のセル数] というのが前提です、(2) ページャー行で RowCreated イベントが発生した際、[データ行] < [PageSize] であればその差の分空のデータ行を生成し GridView に追加する・・・ということです。
そのコードは以下のようになります。コメントに上記 (1), (2) の詳細を書きましたので見てください。データベースは、Microsoft が提供しているサンプル Northwind の Products テーブルを使っています。
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
// データ行のセル数
int numberOfCells = 0;
protected void GridView1_RowCreated(object sender,
GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
// ヘッダ行のセル数=データ行のセル数が前提
numberOfCells = e.Row.Cells.Count;
}
else if (e.Row.RowType == DataControlRowType.DataRow)
{
// データ行では何もしない
}
else if (e.Row.RowType == DataControlRowType.Footer)
{
// フッタ行でも何もしない。ページャー行よりこち
// らの方のイベント発生が先になるが
}
else if (e.Row.RowType == DataControlRowType.Pager)
{
// AllowPaging="False" に設定されているとここに
// 制御は飛んでこない。なので、データ行追加の小
// 細工はここで行った方がよさそう。
GridView gridView = (GridView)sender;
int numberOfRows = gridView.Rows.Count;
int pageSize = gridView.PageSize;
// データ行 < PageSize の場合、その差の分だけ
// 空のデータ行とその中身(空セル)を生成
for (int i = numberOfRows; i < pageSize; i++)
{
GridViewRow row = new GridViewRow(
i,
-1,
DataControlRowType.DataRow,
DataControlRowState.Normal);
for (int j = 0; j < numberOfCells; j++)
{
TableCell cell = new TableCell();
row.Cells.Add(cell);
}
// 空のデータ行を GridView に追加。
// Collection の中の順番は Footer/Pager 行の
// 後になるが、HTML にレンダリングされる時は
// 期待した順序になる。上の GridViewRow のコ
// ンストラクタで設定した i (RowIndex) と
// DataControlRowType.DataRow を見ている?
gridView.Controls[0].Controls.Add(row);
}
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<style type="text/css">
table tr
{
/* 行(空行を含む)の高さ設定 */
height: 30px;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:SqlDataSource ID="SqlDataSource1"
runat="server"
ConnectionString="<%$ ConnectionStrings:Northwind %>"
SelectCommand="SELECT * FROM [Products]">
</asp:SqlDataSource>
<asp:GridView ID="GridView1" runat="server"
AllowPaging="True"
AutoGenerateColumns="False"
DataKeyNames="ProductID"
DataSourceID="SqlDataSource1"
OnRowCreated="GridView1_RowCreated">
<Columns>
<asp:BoundField DataField="ProductID"
HeaderText="ProductID" InsertVisible="False"
ReadOnly="True" SortExpression="ProductID" />
<asp:BoundField DataField="ProductName"
HeaderText="ProductName"
SortExpression="ProductName" />
<asp:BoundField DataField="SupplierID"
HeaderText="SupplierID"
SortExpression="SupplierID" />
<asp:BoundField DataField="CategoryID"
HeaderText="CategoryID"
SortExpression="CategoryID" />
<asp:BoundField DataField="QuantityPerUnit"
HeaderText="QuantityPerUnit"
SortExpression="QuantityPerUnit" />
<asp:BoundField DataField="UnitPrice"
HeaderText="UnitPrice"
SortExpression="UnitPrice" />
<asp:BoundField DataField="UnitsInStock"
HeaderText="UnitsInStock"
SortExpression="UnitsInStock" />
<asp:BoundField DataField="UnitsOnOrder"
HeaderText="UnitsOnOrder"
SortExpression="UnitsOnOrder" />
<asp:BoundField DataField="ReorderLevel"
HeaderText="ReorderLevel"
SortExpression="ReorderLevel" />
<asp:CheckBoxField DataField="Discontinued"
HeaderText="Discontinued"
SortExpression="Discontinued" />
</Columns>
</asp:GridView>
</div>
</form>
</body>
</html>