0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【C#】Web FormのGridViewを使った高速化

Posted at

C#ASP.NET Web FormsGridViewを使った表示の高速化についてのコードです。
データベースはSQL serverを使っています。

完成イメージ

こんな感じでページングが切り替わります。
image.png

image.png

ブラウザ評価ツール「Lighthouse」の結果です。
image.png

フロント側のコード

sample5.aspx
<%@ 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>
                        &nbsp;
                    </ItemTemplate>
                </asp:Repeater>
            </div>
            </form>
        </tbody>
    </table>
</body>
</html>

サーバ側のコード

sample5.aspx.cs
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; }
    }

}

トラブルシューティング

ページネーションは表示できたが、番号リンクを押してもデータが切り替わらない

(修正前)
sample5.aspx
<%@ 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>
                        &nbsp;
                    </ItemTemplate>
                </asp:Repeater>
            </div>
            </form>
        </tbody>
    </table>
</body>
</html>
sample5.aspx.cs
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の下記の箇所がバグの原因です。

sample5.aspx.cs
string cacheKey = $"EmployeeList_Page";

このように、すべてのページで同じキャッシュキーを使っているためpageIndex を変えても 同じデータがキャッシュから取得されてしまう
したがって、結果としてページを切り替えても内容が変わらない、という状態になります。

✅ 解決策:キャッシュキーにページ番号を含める!

sample5.apsx.cs
// ✅ キャッシュキーにページ番号を含める!
string cacheKey = $"EmployeeList_Page{pageIndex}_{sortExpression}_{sortDirection}";

修正後のコードはこちら⇩

sample5.aspx.cs
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関数に初期値をセットしたが、画面にページリングが表示できない

(修正前)

sample.aspx
<%@ 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>
                        &nbsp;
                    </ItemTemplate>
                </asp:Repeater>
            </div>
            </form>
        </tbody>
    </table>
</body>
</html>

(原因)

ページング(ページリンク)が表示されない主な理由は、LoadPager() が呼び出されていない ことが原因です。

✅ 解決方法

Page_Load に LoadPager() を追加

以下のように、IsPostBack == false のときに LoadPager() を呼び出します:

sample5.aspx.cs
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: オブジェクト参照がオブジェクト インスタンスに設定されていません。

(修正前)

sample5.aspx
<%@ 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>
                        &nbsp;
                    </ItemTemplate>
                </asp:Repeater>
            </div>
            </form>
        </tbody>
    </table>
</body>
</html>
sample5.aspx.cs
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; }
    }

}

✅ エラーの内容

sample5.aspx.cs
int pageIndex = (int)ViewState["PageIndex"];
(エラー内容)
System.NullReferenceException: オブジェクト参照がオブジェクト インスタンスに設定されていません。

✅ 原因

ViewState["PageIndex"] nullの状態でキャスト されているためです。

Page_Load() の最初の読み込み(!IsPostBack)時にViewState["PageIndex"]を設定していない。

その状態でLoadGridViewCache()を呼び出し、null (int)にキャストしたため、例外が発生。

✅解決方法

Page_Load内に初期値をセットします

sample5.aspx.cs
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」について

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?