C#
のASP.NET Web Forms
のGridView
を使った表示の高速化についてのコードです。
データベースはSQL server
を使っています。
完成イメージ
フロント側のコード
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="sample5.aspx.cs" Inherits="WebApplicationWebForm.sample5" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<!--検証1-->
<table>
<thead>
<tr>
<th>従業員ID</th>
<th>所属部署</th>
<th>所属課</th>
<th>役職</th>
<th>従業員名</th>
<th>性別</th>
<th>IPaddress</th>
<th>IPaddressの割り振り</th>
</tr>
</thead>
<tbody>
<form id="form2" runat="server">
<asp:GridView ID="GridViewClass" runat="server"
AllowPaging="true" PageSize="2"
AutoGenerateColumns="false"
AllowSorting="true"
OnSorting="GridViewClass_Sorting"
OnPageIndexChanging="GridViewClass_PageIndexChanging"
CssClass="table"
PagerSettings-Mode="NumericFirstLast"
PagerSettings-FirstPageText="先頭"
PagerSettings-LastPageText="最後尾"
PagerSettings-PageButtonCount="5"
PagerStyle-HorizontalAlign="Center"
PagerStyle-CssClass="pager-style">
<Columns>
<asp:BoundField DataField="employeeId" HeaderText="従業員ID" SortExpression="employeeId" />
<asp:BoundField DataField="department" HeaderText="所属部署" SortExpression="department" />
<asp:BoundField DataField="section" HeaderText="所属課" SortExpression="section" />
<asp:BoundField DataField="jobclass" HeaderText="役職" SortExpression="jobclass" />
<asp:BoundField DataField="name" HeaderText="従業員名" SortExpression="name" />
<asp:BoundField DataField="sex" HeaderText="性別" SortExpression="sex" />
<asp:BoundField DataField="ipaddress" HeaderText="IPaddress" SortExpression="ipaddress" />
<asp:BoundField DataField="ipaddressalocation" HeaderText="IPaddressの割り振り" SortExpression="ipaddressalocation" />
</Columns>
</asp:GridView>
<!-- ✅ ページングリンクをRepeaterで作成 -->
<div style="text-align:center; margin-top:10px;">
<asp:Repeater ID="PagerRepeater" runat="server" OnItemCommand="PagerRepeater_ItemCommand">
<ItemTemplate>
<asp:LinkButton runat="server" CommandName="Page" CommandArgument='<%# Eval("PageIndex") %>'>
<%# Eval("DisplayText") %>
</asp:LinkButton>
</ItemTemplate>
</asp:Repeater>
</div>
</form>
</tbody>
</table>
</body>
</html>
サーバ側のコード
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;//接続情報取得用に追加
using System.Data.SqlClient;// SQL server用に追加
using System.Data;//ストアド利用でCommandType用
using WebApplicationWebForm.Models;//追加
using System.Net.Http;//追加
using System.Diagnostics;//追加
namespace WebApplicationWebForm
{
public partial class sample5 : System.Web.UI.Page
{
private int PageSize => 2;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState["SortExpression"] = "employeeId";
ViewState["SortDirection"] = "ASC";
ViewState["PageIndex"] = 0; // ←これを追加!
LoadGridViewCache();//0, GridViewClass.PageSize
LoadPager(); // ← ✅ これが必要!
}
}
/// <summary>
/// ページング対応イベントの追加
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void GridViewClass_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridViewClass.PageIndex = e.NewPageIndex;
LoadGridViewCache();//e.NewPageIndex, GridViewClass.PageSize
}
/// <summary>
/// ソート対応イベントの追加
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void GridViewClass_Sorting(object sender, GridViewSortEventArgs e)
{
string sortExpression = e.SortExpression;
string currentSortDirection = ViewState["SortDirection"] as string ?? "ASC";
string newSortDirection = currentSortDirection == "ASC" ? "DESC" : "ASC";
ViewState["SortExpression"] = sortExpression;
ViewState["SortDirection"] = newSortDirection;
LoadGridViewCache();//GridViewClass.PageIndex, GridViewClass.PageSize
}
private void LoadGridViewCache()//int pageIndex, int pageSize
{
int pageIndex = (int)ViewState["PageIndex"];
int offset = pageIndex * PageSize;
string sortExpression = ViewState["SortExpression"] as string ?? "employeeId";
string sortDirection = ViewState["SortDirection"] as string ?? "ASC";
string cacheKey = $"EmployeeList_Page{pageIndex}_{sortExpression}_{sortDirection}";
//string cacheKey = $"EmployeeList_Page{pageIndex}_Size{pageSize}_Sort{sortExpression}_{sortDirection}";
List<Sample5Employee> employeeList = HttpContext.Current.Cache[cacheKey] as List<Sample5Employee>;
if (employeeList == null)
{
employeeList = new List<Sample5Employee>();
string connStr = ConfigurationManager.ConnectionStrings["sqlserver"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connStr))
{
string sql = $@"
SELECT employeeId, department, section, jobclass, name, ipaddress, sex, ipaddressalocation
FROM [test].[dbo].[employee]
ORDER BY {sortExpression} {sortDirection}
OFFSET (@Offset) ROWS FETCH NEXT @PageSize ROWS ONLY";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
offset = pageIndex * PageSize;
cmd.Parameters.AddWithValue("@Offset", offset);
cmd.Parameters.AddWithValue("@PageSize", PageSize);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Sample5Employee model = new Sample5Employee
{
EmployeeId = reader["employeeId"] != DBNull.Value ? Convert.ToInt32(reader["employeeId"]) : 0,
Department = reader["department"].ToString(),
Section = reader["section"].ToString(),
JobClass = reader["jobclass"].ToString(),
Name = reader["name"].ToString(),
Ipaddress = reader["ipaddress"].ToString(),
Sex = reader["sex"].ToString(),
IpaddressAlocation = reader["ipaddressalocation"] != DBNull.Value ? Convert.ToBoolean(reader["ipaddressalocation"]) : false
};
employeeList.Add(model);
}
}
}
}
// キャッシュ登録
HttpContext.Current.Cache.Insert(
cacheKey,
employeeList,
null,
DateTime.Now.AddMinutes(5),
System.Web.Caching.Cache.NoSlidingExpiration
);
}
GridViewClass.DataSource = employeeList;
GridViewClass.DataBind();
}
protected void PagerRepeater_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "Page")
{
ViewState["PageIndex"] = Convert.ToInt32(e.CommandArgument);
LoadGridViewCache();
LoadPager();
}
}
private string SortExpression
{
get => ViewState["SortExpression"] as string ?? "employeeId";
set => ViewState["SortExpression"] = value;
}
private string SortDirection
{
get => ViewState["SortDirection"] as string ?? "ASC";
set => ViewState["SortDirection"] = value;
}
private void LoadPager()
{
int total = GetTotalRowCount();
int totalPages = (int)Math.Ceiling(total / (double)PageSize);
var pagerItems = new List<dynamic>();
// 先頭
pagerItems.Add(new { PageIndex = 0, DisplayText = "先頭" });
// 番号
for (int i = 0; i < totalPages; i++)
{
pagerItems.Add(new { PageIndex = i, DisplayText = (i + 1).ToString() });
}
// 最後尾
pagerItems.Add(new { PageIndex = totalPages - 1, DisplayText = "最後尾" });
PagerRepeater.DataSource = pagerItems;
PagerRepeater.DataBind();
}
private int GetTotalRowCount()
{
string connStr = ConfigurationManager.ConnectionStrings["sqlserver"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connStr))
{
string sql = "SELECT COUNT(*) FROM [test].[dbo].[employee]";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
conn.Open();
return (int)cmd.ExecuteScalar();
}
}
}
}
public class Sample5Employee
{
public int EmployeeId { get; set; }
public string Department { get; set; }
public string Section { get; set; }
public string JobClass { get; set; }
public string Name { get; set; }
public string Ipaddress { get; set; }
public string Sex { get; set; }
public bool IpaddressAlocation { get; set; }
}
}
トラブルシューティング
ページネーションは表示できたが、番号リンクを押してもデータが切り替わらない
(修正前)
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="sample5.aspx.cs" Inherits="WebApplicationWebForm.sample5" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<!--検証1-->
<table>
<thead>
<tr>
<th>従業員ID</th>
<th>所属部署</th>
<th>所属課</th>
<th>役職</th>
<th>従業員名</th>
<th>性別</th>
<th>IPaddress</th>
<th>IPaddressの割り振り</th>
</tr>
</thead>
<tbody>
<form id="form2" runat="server">
<asp:GridView ID="GridViewClass" runat="server"
AllowPaging="true" PageSize="2"
AutoGenerateColumns="false"
AllowSorting="true"
OnSorting="GridViewClass_Sorting"
OnPageIndexChanging="GridViewClass_PageIndexChanging"
CssClass="table"
PagerSettings-Mode="NumericFirstLast"
PagerSettings-FirstPageText="先頭"
PagerSettings-LastPageText="最後尾"
PagerSettings-PageButtonCount="5"
PagerStyle-HorizontalAlign="Center"
PagerStyle-CssClass="pager-style">
<Columns>
<asp:BoundField DataField="employeeId" HeaderText="従業員ID" SortExpression="employeeId" />
<asp:BoundField DataField="department" HeaderText="所属部署" SortExpression="department" />
<asp:BoundField DataField="section" HeaderText="所属課" SortExpression="section" />
<asp:BoundField DataField="jobclass" HeaderText="役職" SortExpression="jobclass" />
<asp:BoundField DataField="name" HeaderText="従業員名" SortExpression="name" />
<asp:BoundField DataField="sex" HeaderText="性別" SortExpression="sex" />
<asp:BoundField DataField="ipaddress" HeaderText="IPaddress" SortExpression="ipaddress" />
<asp:BoundField DataField="ipaddressalocation" HeaderText="IPaddressの割り振り" SortExpression="ipaddressalocation" />
</Columns>
</asp:GridView>
<!-- ✅ ページングリンクをRepeaterで作成 -->
<div style="text-align:center; margin-top:10px;">
<asp:Repeater ID="PagerRepeater" runat="server" OnItemCommand="PagerRepeater_ItemCommand">
<ItemTemplate>
<asp:LinkButton runat="server" CommandName="Page" CommandArgument='<%# Eval("PageIndex") %>'>
<%# Eval("DisplayText") %>
</asp:LinkButton>
</ItemTemplate>
</asp:Repeater>
</div>
</form>
</tbody>
</table>
</body>
</html>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;//接続情報取得用に追加
using System.Data.SqlClient;// SQL server用に追加
using System.Data;//ストアド利用でCommandType用
using WebApplicationWebForm.Models;//追加
using System.Net.Http;//追加
using System.Diagnostics;//追加
namespace WebApplicationWebForm
{
public partial class sample5 : System.Web.UI.Page
{
private int PageSize => 2;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState["SortExpression"] = "employeeId";
ViewState["SortDirection"] = "ASC";
ViewState["PageIndex"] = 0; // ←これを追加!
LoadGridViewCache();//0, GridViewClass.PageSize
LoadPager(); // ← ✅ これが必要!
}
}
/// <summary>
/// ページング対応イベントの追加
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void GridViewClass_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridViewClass.PageIndex = e.NewPageIndex;
LoadGridViewCache();//e.NewPageIndex, GridViewClass.PageSize
}
/// <summary>
/// ソート対応イベントの追加
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void GridViewClass_Sorting(object sender, GridViewSortEventArgs e)
{
string sortExpression = e.SortExpression;
string currentSortDirection = ViewState["SortDirection"] as string ?? "ASC";
string newSortDirection = currentSortDirection == "ASC" ? "DESC" : "ASC";
ViewState["SortExpression"] = sortExpression;
ViewState["SortDirection"] = newSortDirection;
LoadGridViewCache();//GridViewClass.PageIndex, GridViewClass.PageSize
}
private void LoadGridViewCache()//int pageIndex, int pageSize
{
int pageIndex = (int)ViewState["PageIndex"];
int offset = pageIndex * PageSize;
string sortExpression = ViewState["SortExpression"] as string ?? "employeeId";
string sortDirection = ViewState["SortDirection"] as string ?? "ASC";
string cacheKey = $"EmployeeList_Page";
//string cacheKey = $"EmployeeList_Page{pageIndex}_Size{pageSize}_Sort{sortExpression}_{sortDirection}";
List<Sample5Employee> employeeList = HttpContext.Current.Cache[cacheKey] as List<Sample5Employee>;
if (employeeList == null)
{
employeeList = new List<Sample5Employee>();
string connStr = ConfigurationManager.ConnectionStrings["sqlserver"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connStr))
{
string sql = $@"
SELECT employeeId, department, section, jobclass, name, ipaddress, sex, ipaddressalocation
FROM [test].[dbo].[employee]
ORDER BY {sortExpression} {sortDirection}
OFFSET (@Offset) ROWS FETCH NEXT @PageSize ROWS ONLY";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
offset = pageIndex * PageSize;
cmd.Parameters.AddWithValue("@Offset", offset);
cmd.Parameters.AddWithValue("@PageSize", PageSize);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Sample5Employee model = new Sample5Employee
{
EmployeeId = reader["employeeId"] != DBNull.Value ? Convert.ToInt32(reader["employeeId"]) : 0,
Department = reader["department"].ToString(),
Section = reader["section"].ToString(),
JobClass = reader["jobclass"].ToString(),
Name = reader["name"].ToString(),
Ipaddress = reader["ipaddress"].ToString(),
Sex = reader["sex"].ToString(),
IpaddressAlocation = reader["ipaddressalocation"] != DBNull.Value ? Convert.ToBoolean(reader["ipaddressalocation"]) : false
};
employeeList.Add(model);
}
}
}
}
// キャッシュ登録
HttpContext.Current.Cache.Insert(
cacheKey,
employeeList,
null,
DateTime.Now.AddMinutes(5),
System.Web.Caching.Cache.NoSlidingExpiration
);
}
GridViewClass.DataSource = employeeList;
GridViewClass.DataBind();
}
protected void PagerRepeater_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "Page")
{
ViewState["PageIndex"] = Convert.ToInt32(e.CommandArgument);
LoadGridViewCache();
LoadPager();
}
}
private string SortExpression
{
get => ViewState["SortExpression"] as string ?? "employeeId";
set => ViewState["SortExpression"] = value;
}
private string SortDirection
{
get => ViewState["SortDirection"] as string ?? "ASC";
set => ViewState["SortDirection"] = value;
}
private void LoadPager()
{
int total = GetTotalRowCount();
int totalPages = (int)Math.Ceiling(total / (double)PageSize);
var pagerItems = new List<dynamic>();
// 先頭
pagerItems.Add(new { PageIndex = 0, DisplayText = "先頭" });
// 番号
for (int i = 0; i < totalPages; i++)
{
pagerItems.Add(new { PageIndex = i, DisplayText = (i + 1).ToString() });
}
// 最後尾
pagerItems.Add(new { PageIndex = totalPages - 1, DisplayText = "最後尾" });
PagerRepeater.DataSource = pagerItems;
PagerRepeater.DataBind();
}
private int GetTotalRowCount()
{
string connStr = ConfigurationManager.ConnectionStrings["sqlserver"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connStr))
{
string sql = "SELECT COUNT(*) FROM [test].[dbo].[employee]";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
conn.Open();
return (int)cmd.ExecuteScalar();
}
}
}
}
public class Sample5Employee
{
public int EmployeeId { get; set; }
public string Department { get; set; }
public string Section { get; set; }
public string JobClass { get; set; }
public string Name { get; set; }
public string Ipaddress { get; set; }
public string Sex { get; set; }
public bool IpaddressAlocation { get; set; }
}
}
(原因)
番号リンクを押しても データが切り替わらない原因 は、LoadGridViewCache() が「現在のページのデータ」を 正しく取得していない からです。
✅ 原因の本質
sample5.aspx.cs
の下記の箇所がバグの原因です。
string cacheKey = $"EmployeeList_Page";
このように、すべてのページで同じキャッシュキーを使っているため、pageIndex
を変えても 同じデータがキャッシュから取得されてしまう
したがって、結果としてページを切り替えても内容が変わらない、という状態になります。
✅ 解決策:キャッシュキーにページ番号を含める!
// ✅ キャッシュキーにページ番号を含める!
string cacheKey = $"EmployeeList_Page{pageIndex}_{sortExpression}_{sortDirection}";
修正後のコードはこちら⇩
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;//接続情報取得用に追加
using System.Data.SqlClient;// SQL server用に追加
using System.Data;//ストアド利用でCommandType用
using WebApplicationWebForm.Models;//追加
using System.Net.Http;//追加
using System.Diagnostics;//追加
namespace WebApplicationWebForm
{
public partial class sample5 : System.Web.UI.Page
{
private int PageSize => 2;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState["SortExpression"] = "employeeId";
ViewState["SortDirection"] = "ASC";
ViewState["PageIndex"] = 0; // ←これを追加!
LoadGridViewCache();//0, GridViewClass.PageSize
LoadPager(); // ← ✅ これが必要!
}
}
/// <summary>
/// ページング対応イベントの追加
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void GridViewClass_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridViewClass.PageIndex = e.NewPageIndex;
LoadGridViewCache();//e.NewPageIndex, GridViewClass.PageSize
}
/// <summary>
/// ソート対応イベントの追加
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void GridViewClass_Sorting(object sender, GridViewSortEventArgs e)
{
string sortExpression = e.SortExpression;
string currentSortDirection = ViewState["SortDirection"] as string ?? "ASC";
string newSortDirection = currentSortDirection == "ASC" ? "DESC" : "ASC";
ViewState["SortExpression"] = sortExpression;
ViewState["SortDirection"] = newSortDirection;
LoadGridViewCache();//GridViewClass.PageIndex, GridViewClass.PageSize
}
private void LoadGridViewCache()//int pageIndex, int pageSize
{
int pageIndex = (int)ViewState["PageIndex"];
int offset = pageIndex * PageSize;
string sortExpression = ViewState["SortExpression"] as string ?? "employeeId";
string sortDirection = ViewState["SortDirection"] as string ?? "ASC";
string cacheKey = $"EmployeeList_Page{pageIndex}_{sortExpression}_{sortDirection}";
//string cacheKey = $"EmployeeList_Page{pageIndex}_Size{pageSize}_Sort{sortExpression}_{sortDirection}";
List<Sample5Employee> employeeList = HttpContext.Current.Cache[cacheKey] as List<Sample5Employee>;
if (employeeList == null)
{
employeeList = new List<Sample5Employee>();
string connStr = ConfigurationManager.ConnectionStrings["sqlserver"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connStr))
{
string sql = $@"
SELECT employeeId, department, section, jobclass, name, ipaddress, sex, ipaddressalocation
FROM [test].[dbo].[employee]
ORDER BY {sortExpression} {sortDirection}
OFFSET (@Offset) ROWS FETCH NEXT @PageSize ROWS ONLY";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
offset = pageIndex * PageSize;
cmd.Parameters.AddWithValue("@Offset", offset);
cmd.Parameters.AddWithValue("@PageSize", PageSize);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Sample5Employee model = new Sample5Employee
{
EmployeeId = reader["employeeId"] != DBNull.Value ? Convert.ToInt32(reader["employeeId"]) : 0,
Department = reader["department"].ToString(),
Section = reader["section"].ToString(),
JobClass = reader["jobclass"].ToString(),
Name = reader["name"].ToString(),
Ipaddress = reader["ipaddress"].ToString(),
Sex = reader["sex"].ToString(),
IpaddressAlocation = reader["ipaddressalocation"] != DBNull.Value ? Convert.ToBoolean(reader["ipaddressalocation"]) : false
};
employeeList.Add(model);
}
}
}
}
// キャッシュ登録
HttpContext.Current.Cache.Insert(
cacheKey,
employeeList,
null,
DateTime.Now.AddMinutes(5),
System.Web.Caching.Cache.NoSlidingExpiration
);
}
GridViewClass.DataSource = employeeList;
GridViewClass.DataBind();
}
protected void PagerRepeater_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "Page")
{
ViewState["PageIndex"] = Convert.ToInt32(e.CommandArgument);
LoadGridViewCache();
LoadPager();
}
}
private string SortExpression
{
get => ViewState["SortExpression"] as string ?? "employeeId";
set => ViewState["SortExpression"] = value;
}
private string SortDirection
{
get => ViewState["SortDirection"] as string ?? "ASC";
set => ViewState["SortDirection"] = value;
}
private void LoadPager()
{
int total = GetTotalRowCount();
int totalPages = (int)Math.Ceiling(total / (double)PageSize);
var pagerItems = new List<dynamic>();
// 先頭
pagerItems.Add(new { PageIndex = 0, DisplayText = "先頭" });
// 番号
for (int i = 0; i < totalPages; i++)
{
pagerItems.Add(new { PageIndex = i, DisplayText = (i + 1).ToString() });
}
// 最後尾
pagerItems.Add(new { PageIndex = totalPages - 1, DisplayText = "最後尾" });
PagerRepeater.DataSource = pagerItems;
PagerRepeater.DataBind();
}
private int GetTotalRowCount()
{
string connStr = ConfigurationManager.ConnectionStrings["sqlserver"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connStr))
{
string sql = "SELECT COUNT(*) FROM [test].[dbo].[employee]";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
conn.Open();
return (int)cmd.ExecuteScalar();
}
}
}
}
public class Sample5Employee
{
public int EmployeeId { get; set; }
public string Department { get; set; }
public string Section { get; set; }
public string JobClass { get; set; }
public string Name { get; set; }
public string Ipaddress { get; set; }
public string Sex { get; set; }
public bool IpaddressAlocation { get; set; }
}
}
Page_Load関数に初期値をセットしたが、画面にページリングが表示できない
(修正前)
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="sample5.aspx.cs" Inherits="WebApplicationWebForm.sample5" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<!--検証1-->
<table>
<thead>
<tr>
<th>従業員ID</th>
<th>所属部署</th>
<th>所属課</th>
<th>役職</th>
<th>従業員名</th>
<th>性別</th>
<th>IPaddress</th>
<th>IPaddressの割り振り</th>
</tr>
</thead>
<tbody>
<form id="form2" runat="server">
<asp:GridView ID="GridViewClass" runat="server"
AllowPaging="true" PageSize="2"
AutoGenerateColumns="false"
AllowSorting="true"
OnSorting="GridViewClass_Sorting"
OnPageIndexChanging="GridViewClass_PageIndexChanging"
CssClass="table"
PagerSettings-Mode="NumericFirstLast"
PagerSettings-FirstPageText="先頭"
PagerSettings-LastPageText="最後尾"
PagerSettings-PageButtonCount="5"
PagerStyle-HorizontalAlign="Center"
PagerStyle-CssClass="pager-style">
<Columns>
<asp:BoundField DataField="employeeId" HeaderText="従業員ID" SortExpression="employeeId" />
<asp:BoundField DataField="department" HeaderText="所属部署" SortExpression="department" />
<asp:BoundField DataField="section" HeaderText="所属課" SortExpression="section" />
<asp:BoundField DataField="jobclass" HeaderText="役職" SortExpression="jobclass" />
<asp:BoundField DataField="name" HeaderText="従業員名" SortExpression="name" />
<asp:BoundField DataField="sex" HeaderText="性別" SortExpression="sex" />
<asp:BoundField DataField="ipaddress" HeaderText="IPaddress" SortExpression="ipaddress" />
<asp:BoundField DataField="ipaddressalocation" HeaderText="IPaddressの割り振り" SortExpression="ipaddressalocation" />
</Columns>
</asp:GridView>
<!-- ✅ ページングリンクをRepeaterで作成 -->
<div style="text-align:center; margin-top:10px;">
<asp:Repeater ID="PagerRepeater" runat="server" OnItemCommand="PagerRepeater_ItemCommand">
<ItemTemplate>
<asp:LinkButton runat="server" CommandName="Page" CommandArgument='<%# Eval("PageIndex") %>'>
<%# Eval("DisplayText") %>
</asp:LinkButton>
</ItemTemplate>
</asp:Repeater>
</div>
</form>
</tbody>
</table>
</body>
</html>
(原因)
ページング(ページリンク)が表示されない主な理由は、LoadPager() が呼び出されていない ことが原因です。
✅ 解決方法
Page_Load に LoadPager() を追加
以下のように、IsPostBack == false のときに LoadPager() を呼び出します:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState["SortExpression"] = "employeeId";
ViewState["SortDirection"] = "ASC";
ViewState["PageIndex"] = 0;
LoadGridViewCache();
LoadPager(); // ← ✅ これが必要!
}
}
[sample5.aspx.cs]のLoadGridViewCache関数の「int pageIndex = (int)ViewState["PageIndex"];」の箇所でエラー「オブジェクト参照がオブジェクト インスタンスに設定されていません。説明: 現在の Web 要求を実行中に、ハンドルされていない例外が発生しました。エラーに関する詳細および例外の発生場所については、スタック トレースを参照してください。例外の詳細: System.NullReferenceException: オブジェクト参照がオブジェクト インスタンスに設定されていません。
(修正前)
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="sample5.aspx.cs" Inherits="WebApplicationWebForm.sample5" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<!--検証1-->
<table>
<thead>
<tr>
<th>従業員ID</th>
<th>所属部署</th>
<th>所属課</th>
<th>役職</th>
<th>従業員名</th>
<th>性別</th>
<th>IPaddress</th>
<th>IPaddressの割り振り</th>
</tr>
</thead>
<tbody>
<form id="form2" runat="server">
<asp:GridView ID="GridViewClass" runat="server"
AllowPaging="true" PageSize="2"
AutoGenerateColumns="false"
AllowSorting="true"
OnSorting="GridViewClass_Sorting"
OnPageIndexChanging="GridViewClass_PageIndexChanging"
CssClass="table"
PagerSettings-Mode="NumericFirstLast"
PagerSettings-FirstPageText="先頭"
PagerSettings-LastPageText="最後尾"
PagerSettings-PageButtonCount="5"
PagerStyle-HorizontalAlign="Center"
PagerStyle-CssClass="pager-style">
<Columns>
<asp:BoundField DataField="employeeId" HeaderText="従業員ID" SortExpression="employeeId" />
<asp:BoundField DataField="department" HeaderText="所属部署" SortExpression="department" />
<asp:BoundField DataField="section" HeaderText="所属課" SortExpression="section" />
<asp:BoundField DataField="jobclass" HeaderText="役職" SortExpression="jobclass" />
<asp:BoundField DataField="name" HeaderText="従業員名" SortExpression="name" />
<asp:BoundField DataField="sex" HeaderText="性別" SortExpression="sex" />
<asp:BoundField DataField="ipaddress" HeaderText="IPaddress" SortExpression="ipaddress" />
<asp:BoundField DataField="ipaddressalocation" HeaderText="IPaddressの割り振り" SortExpression="ipaddressalocation" />
</Columns>
</asp:GridView>
<!-- ✅ ページングリンクをRepeaterで作成 -->
<div style="text-align:center; margin-top:10px;">
<asp:Repeater ID="PagerRepeater" runat="server" OnItemCommand="PagerRepeater_ItemCommand">
<ItemTemplate>
<asp:LinkButton runat="server" CommandName="Page" CommandArgument='<%# Eval("PageIndex") %>'>
<%# Eval("DisplayText") %>
</asp:LinkButton>
</ItemTemplate>
</asp:Repeater>
</div>
</form>
</tbody>
</table>
</body>
</html>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;//接続情報取得用に追加
using System.Data.SqlClient;// SQL server用に追加
using System.Data;//ストアド利用でCommandType用
using WebApplicationWebForm.Models;//追加
using System.Net.Http;//追加
using System.Diagnostics;//追加
namespace WebApplicationWebForm
{
public partial class sample5 : System.Web.UI.Page
{
private int PageSize => 2;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState["SortExpression"] = "employeeId";
ViewState["SortDirection"] = "ASC";
LoadGridViewCache();//0, GridViewClass.PageSize
}
}
/// <summary>
/// ページング対応イベントの追加
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void GridViewClass_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridViewClass.PageIndex = e.NewPageIndex;
LoadGridViewCache();//e.NewPageIndex, GridViewClass.PageSize
}
/// <summary>
/// ソート対応イベントの追加
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void GridViewClass_Sorting(object sender, GridViewSortEventArgs e)
{
string sortExpression = e.SortExpression;
string currentSortDirection = ViewState["SortDirection"] as string ?? "ASC";
string newSortDirection = currentSortDirection == "ASC" ? "DESC" : "ASC";
ViewState["SortExpression"] = sortExpression;
ViewState["SortDirection"] = newSortDirection;
LoadGridViewCache();//GridViewClass.PageIndex, GridViewClass.PageSize
}
private void LoadGridViewCache()//int pageIndex, int pageSize
{
int pageIndex = (int)ViewState["PageIndex"];
int offset = pageIndex * PageSize;
string sortExpression = ViewState["SortExpression"] as string ?? "employeeId";
string sortDirection = ViewState["SortDirection"] as string ?? "ASC";
string cacheKey = $"EmployeeList_Page";
//string cacheKey = $"EmployeeList_Page{pageIndex}_Size{pageSize}_Sort{sortExpression}_{sortDirection}";
List<Sample5Employee> employeeList = HttpContext.Current.Cache[cacheKey] as List<Sample5Employee>;
if (employeeList == null)
{
employeeList = new List<Sample5Employee>();
string connStr = ConfigurationManager.ConnectionStrings["sqlserver"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connStr))
{
string sql = $@"
SELECT employeeId, department, section, jobclass, name, ipaddress, sex, ipaddressalocation
FROM [test].[dbo].[employee]
ORDER BY {sortExpression} {sortDirection}
OFFSET (@Offset) ROWS FETCH NEXT @PageSize ROWS ONLY";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
offset = pageIndex * PageSize;
cmd.Parameters.AddWithValue("@Offset", offset);
cmd.Parameters.AddWithValue("@PageSize", PageSize);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Sample5Employee model = new Sample5Employee
{
EmployeeId = reader["employeeId"] != DBNull.Value ? Convert.ToInt32(reader["employeeId"]) : 0,
Department = reader["department"].ToString(),
Section = reader["section"].ToString(),
JobClass = reader["jobclass"].ToString(),
Name = reader["name"].ToString(),
Ipaddress = reader["ipaddress"].ToString(),
Sex = reader["sex"].ToString(),
IpaddressAlocation = reader["ipaddressalocation"] != DBNull.Value ? Convert.ToBoolean(reader["ipaddressalocation"]) : false
};
employeeList.Add(model);
}
}
}
}
// キャッシュ登録
HttpContext.Current.Cache.Insert(
cacheKey,
employeeList,
null,
DateTime.Now.AddMinutes(5),
System.Web.Caching.Cache.NoSlidingExpiration
);
}
GridViewClass.DataSource = employeeList;
GridViewClass.DataBind();
}
protected void PagerRepeater_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "Page")
{
ViewState["PageIndex"] = Convert.ToInt32(e.CommandArgument);
LoadGridViewCache();
LoadPager();
}
}
private string SortExpression
{
get => ViewState["SortExpression"] as string ?? "employeeId";
set => ViewState["SortExpression"] = value;
}
private string SortDirection
{
get => ViewState["SortDirection"] as string ?? "ASC";
set => ViewState["SortDirection"] = value;
}
private void LoadPager()
{
int total = GetTotalRowCount();
int totalPages = (int)Math.Ceiling(total / (double)PageSize);
var pagerItems = new List<dynamic>();
// 先頭
pagerItems.Add(new { PageIndex = 0, DisplayText = "先頭" });
// 番号
for (int i = 0; i < totalPages; i++)
{
pagerItems.Add(new { PageIndex = i, DisplayText = (i + 1).ToString() });
}
// 最後尾
pagerItems.Add(new { PageIndex = totalPages - 1, DisplayText = "最後尾" });
PagerRepeater.DataSource = pagerItems;
PagerRepeater.DataBind();
}
private int GetTotalRowCount()
{
string connStr = ConfigurationManager.ConnectionStrings["sqlserver"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connStr))
{
string sql = "SELECT COUNT(*) FROM [test].[dbo].[employee]";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
conn.Open();
return (int)cmd.ExecuteScalar();
}
}
}
}
public class Sample5Employee
{
public int EmployeeId { get; set; }
public string Department { get; set; }
public string Section { get; set; }
public string JobClass { get; set; }
public string Name { get; set; }
public string Ipaddress { get; set; }
public string Sex { get; set; }
public bool IpaddressAlocation { get; set; }
}
}
✅ エラーの内容
int pageIndex = (int)ViewState["PageIndex"];
(エラー内容)
System.NullReferenceException: オブジェクト参照がオブジェクト インスタンスに設定されていません。
✅ 原因
ViewState["PageIndex"]
がnull
の状態でキャスト されているためです。
Page_Load()
の最初の読み込み(!IsPostBack)
時にViewState["PageIndex"]
を設定していない。
その状態でLoadGridViewCache()
を呼び出し、null
を(int)
にキャストしたため、例外が発生。
✅解決方法
Page_Load
内に初期値をセットします
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState["SortExpression"] = "employeeId";
ViewState["SortDirection"] = "ASC";
ViewState["PageIndex"] = 0; // ←これを追加!
LoadGridViewCache();//0, GridViewClass.PageSize
LoadPager(); // ← ✅ これが必要!
}
}
サイト
■ブラウザの表示評価ツール「LightHouse」について