[ASP.NET 自訂控制項]GridView自訂Pager for .net framework 2.0

在.net framework 2.0裡,使用VS2005,自訂GridView的Pager

,我的Windows Live Writer又在鬧脾氣了,怎麼發佈都沒有錯誤訊息,文章卻沒上來。只好手動貼了。

今天要介紹的,是怎麼在GridView裡面增加自訂的Pager。

請原諒我是個樣式白癡,我只能提供功能跟作法,樣式就請自行設計對應的css吧。

這邊舉的例子,是新增一個可以自行輸入頁碼的TextBox。有需要增加其他的Control,請照樣造句即可。


Download Source Code:GridViewPager.rar


Step1:

一樣新增一個類別庫叫做Joey,接著新增一個類別叫做JoeyGridView.cs並繼承GridView,

這邊我偷懶匯入了Microsoft.VisualBasic NameSpace,因為裡面有需要用到判斷數字,實在懶得自己寫function,就直接用VB內建的IsNumeric()了。

如果不想匯入VB的話,可以參考mis2000Lab大大的文章,[C#]以前在VB語法裡面用慣的 IsNumeric,在C#不見了??,主要還是使用Double.Tryparse()的function,

如果不是double,就自己選用適用的型別吧。

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.VisualBasic;

namespace Joey
{
    public class JoeyGridView: GridView
    {
    }

}

Step2:

接著要覆寫的是OnRowCreated(),當e.row為Pager的時候,我們要插入自訂的Pager。

        #region Override Method
        /// <summary>
        /// 引發 <see cref="E:System.Web.UI.WebControls.GridView.RowCreated"/> 事件,並加入自訂的pager。
        /// </summary>
        /// <param name="e"><see cref="T:System.Web.UI.WebControls.GridViewRowEventArgs"/> 包含事件資料。</param>

        protected override void OnRowCreated(GridViewRowEventArgs e)
        {
            base.OnRowCreated(e);
            if (e.Row.RowType == DataControlRowType.Pager)
            { SettingPager(e.Row); }

        }

        #endregion

Step3:

再來就是精髓所在了,我們自訂Pager,要用TableRow的方式,插入原本的Pager裡。

並自訂新增Control的相關事件出來。

#region Private method:CreatePager
        /// <summary>
        /// Settings the pager.
        /// </summary>
        /// <param name="gridRow">The grid row.</param>

        private void SettingPager(GridViewRow gridRow)
        {
            TableCell newCell = new TableCell();
            TableRow tableRow = new TableRow();
            newCell = CreatePagerTextBox();
            tableRow = GetPagerTableRow(gridRow.Cells[0]);
            tableRow.Cells.Add(newCell);
        }


        /// <summary>
        /// Gets the pager's tablerow.
        /// </summary>
        /// <param name="gridRowCell">The grid row cell.</param>
        /// <returns></returns>

        private TableRow GetPagerTableRow(Control gridRowCell)
        {
            TableRow row = null;
            while (gridRowCell.Controls.Count > 0)
            {
                row = gridRowCell as TableRow;
                if (row != null)
                {
                    break;
                }

                gridRowCell = gridRowCell.Controls[0];
            }

            return row;
        }


        /// <summary>
        /// Creates text box in Grid pager .
        /// </summary>
        /// <returns></returns>

        private TableCell CreatePagerTextBox()
        {
            TextBox sel = new TextBox();
            sel.ID = "PageSizeSelector3";
            sel.Text = Convert.ToString(this.PageIndex + 1);
            sel.AutoPostBack = true;
            sel.EnableViewState = true;
            sel.Width = new Unit(30, UnitType.Pixel);

            sel.TextChanged += new EventHandler(PageChangeSelectorByTextBox_Clicked);

            TableCell newCell = new TableCell();
            newCell.HorizontalAlign = HorizontalAlign.Right;
            newCell.Controls.Add(sel);
            return newCell;
        }

        #endregion

Step4:

最後是對Pager自訂事件的處理,這裡我們做三件事。

  • 當輸入的值非數字時,維持原pageindex。
  • 當輸入值>PageCount時,移至最後頁。
  • 當輸入值比0小時,移至第一頁。
        #region Custom Event
        public event EventHandler PageIndexByTextChanged;
        /// <summary>
        /// Handles the Clicked event of the PageChangeSelectorByTextBox control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        /// <remarks>當輸入的值非數字時,維持原pageindex。
        /// 當輸入值>PageCount時,移至最後頁。
        /// 當輸入值比0小時,移至第一頁</remarks>

        private void PageChangeSelectorByTextBox_Clicked(object sender, System.EventArgs e)
        {
            if (PageIndexByTextChanged != null)
            {
                TextBox ddl = (TextBox)sender;
                string requestedPageSize = ddl.Text;
                GridView grid = this;
                try
                {
                    if (Information.IsNumeric(requestedPageSize) & requestedPageSize.IndexOf(".") == -1)
                    {
                        int intrequestedPageSize = Convert.ToInt32(requestedPageSize);
                        if (intrequestedPageSize == 0)
                        {
                            ddl.Text = Convert.ToString(grid.PageIndex + 1);
                        }

                        else if (intrequestedPageSize <= grid.PageCount && intrequestedPageSize > 0)
                        {

                            grid.PageIndex = intrequestedPageSize - 1;
                        }

                        else if (intrequestedPageSize > grid.PageCount)
                        {

                            grid.PageIndex = grid.PageCount - 1;
                            ddl.Text = Convert.ToString(grid.PageCount);
                        }

                        if (PageIndexByTextChanged != null)
                        {
                            PageIndexByTextChanged(sender, e);
                        }

                    }

                    else
                    {
                        ddl.Text = Convert.ToString(grid.PageIndex + 1);
                    }

                }

                catch (Exception ex)
                {
                    ddl.Text = Convert.ToString(grid.PageIndex + 1);
                }

            }

        }

        #endregion
      

    }

Step5:

就這樣,大功告成。當然這樣的Code還是有美中不足的地方。

就是在TextChanged事件觸發的部分,還是需要額外自己寫Code去做Grid.DataBind()的動作。(跟原生的GridView.PageIndexChanging一樣)

如果有大大可以指導一下怎麼連那一段Code都省下來,小弟在這感激不盡!

建置一下類別庫,產生Joey.dll,加進網站參考裡,在頁面上拉一個JoeyGridView進來。

餵資料給GridView之後,還需額外撰寫事件重bind Grid的資料。(這邊樣式是套GridView的智慧標籤)

aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="JoeyGridViewTest.aspx.cs" Inherits="JoeyGridViewTest" %>

<%@ Register Assembly="Joey" Namespace="Joey" TagPrefix="cc1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>未命名頁面</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <cc1:JoeyGridView ID="JoeyGridView1" runat="server" OnPageIndexByTextChanged="JoeyGridView1_PageIndexByTextChanged" OnPageIndexChanging="JoeyGridView1_PageIndexChanging" AutoGenerateColumns="False" AllowPaging="True" CellPadding="4" ForeColor="#333333" GridLines="None" Width="100%">
            <Columns>
                <asp:BoundField DataField="Text" HeaderText="Text " />
                <asp:BoundField DataField="Value" HeaderText="Value " />
                <asp:BoundField DataField="CreatedDate" HeaderText="CreatedDate " />
            </Columns>
            <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
            <RowStyle BackColor="#EFF3FB" />
            <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
            <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
            <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
            <EditRowStyle BackColor="#2461BF" />
            <AlternatingRowStyle BackColor="White" />
        </cc1:JoeyGridView>
    
    </div>
    </form>
</body>
</html>

cs:資料我就隨便塞了,請原諒我的懶惰。

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;


public partial class JoeyGridViewTest : System.Web.UI.Page
{
    private DataTable _dtDt = new DataTable();
    protected void Page_Load(object sender, EventArgs e)
    {
        _dtDt.Columns.Add("Text");
        _dtDt.Columns.Add("Value");
        _dtDt.Columns.Add("CreatedDate");


        _dtDt.Rows.Add(new string[] { "萬華區", "萬華", "2003/01/01" });
        _dtDt.Rows.Add(new string[] { "中正區", "中正", "2003/01/01" });
        _dtDt.Rows.Add(new string[] { "大同區", "大同", "2005/01/01" });
        _dtDt.Rows.Add(new string[] { "台中市", "台中", "2005/01/01" });
        _dtDt.Rows.Add(new string[] { "大甲鎮", "大甲", "2007/01/01" });
        _dtDt.Rows.Add(new string[] { "台南市", "台南", "2007/01/01" });
        _dtDt.Rows.Add(new string[] { "台北市", "北", "2007/01/01" });
        _dtDt.Rows.Add(new string[] { "台中縣", "中", "2007/01/01" });
        _dtDt.Rows.Add(new string[] { "台南縣", "南", "2010/01/01" });
        _dtDt.Rows.Add(new string[] { "萬華區", "萬華", "2010/01/01" });
        _dtDt.Rows.Add(new string[] { "中正區", "中正", "2010/01/01" });

        if (!IsPostBack)
        {
            this.ViewState["source"] = _dtDt;
            this.JoeyGridView1.DataSource = _dtDt;
            this.JoeyGridView1.DataBind();
        }

    }

    protected void JoeyGridView1_PageIndexByTextChanged(object sender, EventArgs e)
    {
        this.JoeyGridView1.DataSource = this.ViewState["source"];
        string pageindex= ((TextBox)sender).Text;
        this.JoeyGridView1.PageIndex = Convert.ToInt32(pageindex) - 1;
        this.JoeyGridView1.DataBind();
    }


    protected void JoeyGridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
    {
        this.JoeyGridView1.DataSource = this.ViewState["source"];
        this.JoeyGridView1.PageIndex = e.NewPageIndex;
        this.JoeyGridView1.DataBind();
    }

}

(忘記插上結果畫面…真的老了)

最後感謝mis2000lab大大的判斷C#自訂IsNumeric的文章。

我相信我這個自訂Pager的作法一定還有很大的改進空間,希望拋磚引玉一下,能有高手或其他大大們給予更多的建議。


或許您會對下列培訓課程感興趣:

  1. 2019/12/21(六)~2019/12/22(日):演化式設計:測試驅動開發與持續重構 第七梯次(台北)
  2. 2020/1/4(六)~2020/1/5(日):Clean Coder:DI 與 AOP 進階實戰 第三梯次(台北)
  3. 2020/02/08(六):【針對遺留代碼加入單元測試的藝術】 第八梯次(台北)
  4. 2020/02/09(日):【極速開發+】 第九梯次(台北)
  5. 2020/02/28(五)~2020/3/1(日) C#進階設計-從重構學會高易用性與高彈性API設計 第三梯次(台北)

想收到第一手公開培訓課程資訊,或想詢問企業內訓、顧問、教練、諮詢服務的,請洽 Facebook 粉絲專頁:91敏捷開發之路