locked
ASP.Net GridView Custom Paging Questions. RRS feed

  • 問題

  • Hi

    I am trying to create a custom paging on GridView, by using linkedbutton.

    The process at the moment.
    I retrieve the data from Database to DataTable and populate them into GridView, The data that I retrieve from database to DataTable but it only retrieve the number of records that i need to present at that time with the total number of Record I has from that query (as Integer)E.g. I may have 6000 records in total, but I only want to retrieve the 30 records which will be display on the grid view and 6000 as the total number of record, after the user click on another page number, then it will run the same method and retrieve another 30 records and place it into the GridView.

    Could you give me some advice on How I can achieve that.
    At them moment, I do that by programmatically generate a set of Linkedbutton for the page number, when the user click on it, it will place an variable into URL E.g. url.aspx?pNo=3.

    Is there any way that I can do it on an event so that I can retrieve the page number and run the method there rather than need to place some code on page_load event to check the URL parameter. (I has 5 different gridview on the same aspx page. )

    Sorry about my poor English, how you can still understand my issue.

    Thanks in advanced.

    I tried to register the event into the linked button, unforunately it did not work

    Here is the code i have used

    public void GenerateGV(DataTable tbl, int TotalRecord, int PageNum, int PageSize){

        gv.DataSource = tbl;
        gv.DataBind()

        int NoOfPage = TotalRecord/PageSize

     for(int i = 0; i<=NoOfPage;i++){
                     if (PageNum==i){
                         div_Paging.Controls.Add(new LiteralControl(i.ToString()));
                     }else{

     LinkButton lb = new LinkButton();
     lb.Text=i.ToString();
     lb.PostBackUrl = Request.Path + "?PNo=" + i.ToString();
     lb.CommandArgument = i.ToString();
     lb.Click += new EventHandler(example);
     lb.Click += example;
     lb.OnClientClick = "return false";
     lb.Command += example;
    div_Paging.Controls.Add(lb);
    }
    }

      public void example(object sender, EventArgs e)
        {
            LinkButton s = (LinkButton)sender;
            string c = s.CommandArgument;
            string p = s.PostBackUrl;
        //retrieve datatable by parameter...etc...
        }

    I would be grateful, if you can give me some advice and suggestion.
    2008年11月4日 上午 10:15

解答

  • I an concerning about you've put "return false;" in the "OnClientClick" property of the LinkButton.  It should prevent the postback to the server (please check if your IE did submit something to the server).  In addition, you've actually added the event handler 3 times in your code:

     

    Code Snippet
    lb.Click += new EventHandler(example);
    lb.Click += example;
    lb.Command += example;

     

     

    That means the event handler will execute 3 time for 1 postback action.

     

    I think you can keep your code simple first.  I got the following works fine:

     

    Code Snippet

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;

    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            LinkButton lb = new LinkButton();
            lb.Text = "1";
            lb.Click += example;

            this.form1.Controls.Add(lb);
        }

        private void example(object sender, EventArgs e)
        {
            LinkButton s = (LinkButton)sender;
            Label1.Text = s.Text;
        }
    }

     

     

    The page I used only contains a label named "Label1" and others are default settings from Web site project creation.

    2008年11月5日 上午 06:17
  •  

    Try to think about the follow situation:

     

    For the first time you access the web page, your page will display 1 LinkButton (let's alias it as lb0 and this control has a event handler associated with it), 1 Label (with no text) and 1 Button.

     

    Then you click on the button and got a post back action.  At server side, Page_Load is being executed and now lb0 no longer exists because lb0 will only be created when the page is not pasted back.  After the Page_Load event handler finish, the Button1_Click event handler will be triggered which will create 10 LinkButtons and each of them will associated the click event to a event handler.  And now, the web page will be render back to the client browser which will show 10 LinkButtons, 1 Label (with no text) and 1 Button.

     

    At this point, you click on one of the LinkButton and this will trigger another post back action.  This time, the page object at server side will be created and contains the objects defined on the aspx, i.e. 1 Label and 1 Button only.  Page_Load event handler will be triggered at server side, and no more custom event handler will be executed.  It is because the LinkButtons do not exist before or during the Page_Load event (all custom event handlers will be executed after the Page_Load event).  Hence, the method/event handler "example" will not be executed!

     

    This is why you cannot make the expected result in your code sample.  If you would like to show the LinkButtons dynamically, I prefer to create all necessary controls on the aspx or during the Page_Load event.  Then use the Visible property to control the display status of those controls.

    2008年11月5日 下午 12:16

所有回覆

  • You should be able to utilize the PageIndexChanged event in the GridView object, and you can use the PageIndex property to get current page number.

    2008年11月4日 下午 03:52
  • Hi Raymond

    Thanks for your reply, I guess I may not explain my situation properly.
    For the Grid View I created, I did not use the Paging Feature, and also, I had create the Page Number Manually.

    Is it possible to place a number (Integer) into one of the Grid Views property then It can generate the Page Number for me?
    I only retrieve 30 records out of 6000, so I am not sure if I can still use the Paging feature.

    I would be grateful if you can give me more suggestions.

    Thanks in advance
    2008年11月4日 下午 04:10
  • Just brainstorming... How about associating a drop down box for each of your GridView and store the available page numbers in the drop down box?  After you got the drop down box, you can enable the AutoPostBack property and handle the index change event of the drop down box to perform the page refresh action.  In this case, you can retrieve the page number from the selected item property of the drop down box.

    2008年11月4日 下午 04:52
  • Hi Raymond,

    Thanks for your suggestion, I had done that before, unfortunately, people still prefer to have a range of page number like the original paging thing from ASP.NET.

    Do you have any idea, on how could I achieve it? E.g. register an event handler on the linked button?

    Thanks in advance.
    2008年11月4日 下午 09:29
  • LinkButtont is ok and you can retrieve the selected page number from the Text property of the LinkButton object.

     

    2008年11月5日 上午 04:12
  • HI Raymond

    Thanks for your reply, I did try to use linked button, I am not sure why it did not trigger the method I wrote for it.
    Do you have any idea?

    Here it is the code I did:

    LinkButton lb = new LinkButton();
     lb.Text=i.ToString();
     lb.PostBackUrl = Request.Path + "?PNo=" + i.ToString();
     lb.CommandArgument = i.ToString();
     lb.Click += new EventHandler(example);
     lb.Click += example;
     lb.OnClientClick = "return false";
     lb.Command += example;
    div_Paging.Controls.Add(lb);
    }
    }
    //It never execute the method below = (
      public void example(object sender, EventArgs e)
        {
            LinkButton s = (LinkButton)sender;
            string c = s.CommandArgument;
            string p = s.PostBackUrl;
        //retrieve datatable by parameter...etc...
        }

    Thanks a lot.
    2008年11月5日 上午 05:01
  • I an concerning about you've put "return false;" in the "OnClientClick" property of the LinkButton.  It should prevent the postback to the server (please check if your IE did submit something to the server).  In addition, you've actually added the event handler 3 times in your code:

     

    Code Snippet
    lb.Click += new EventHandler(example);
    lb.Click += example;
    lb.Command += example;

     

     

    That means the event handler will execute 3 time for 1 postback action.

     

    I think you can keep your code simple first.  I got the following works fine:

     

    Code Snippet

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;

    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            LinkButton lb = new LinkButton();
            lb.Text = "1";
            lb.Click += example;

            this.form1.Controls.Add(lb);
        }

        private void example(object sender, EventArgs e)
        {
            LinkButton s = (LinkButton)sender;
            Label1.Text = s.Text;
        }
    }

     

     

    The page I used only contains a label named "Label1" and others are default settings from Web site project creation.

    2008年11月5日 上午 06:17
  • Hi Raymond,

    Thanks for your sample code, I tried it and It work fine on the new page that I created. What mean the method is correct, but when I try to apply it to the custom paging that I did, it does not work = (.

    I did modified my code to remove event handler

    Now I only has
    lb.Click += example;

    I did place a Label into the form as well, but it still did not work...

    Here it is the code for my example method
      public void example(object sender, EventArgs e)
        {
            LinkButton s = (LinkButton)sender;  // <-- I placed a break point here, the code never stop here
            lbl_Err.Text = s.Text;
        }

    And the label did not contain any value as well

    I has one update panel surrounding all the control. E.g. GridView, Paging (linked button) and the label as well.

    I did remove the update panel, unfortunately it still did not work = (.

    I had find that, what it did not work in my situation is because you has added the linked button on the form, but I had added the linked button onto div_paging, after I click on the linked button the linked button that I created disappear.

    Here is the sample code that I done, and is not working. I would be grateful if you can help me get around the problem.


    public partial class main_example : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            //if (!IsPostBack)
            //{
                LinkButton lb = new LinkButton();
                lb.Text = "1";
                lb.Click += example;
                div_Paging.Controls.Add(lb);
          //  }

           
        }

        private void gen()
        {
            for (int i = 0; i < 10; i++)
            {
                LinkButton lb = new LinkButton();
                lb.Text = i.ToString();
                lb.Click += example;
                div_Paging.Controls.Add(lb);
            }
        }

        private void example(object sender, EventArgs e)
        {
            LinkButton s = (LinkButton)sender;
            Label1.Text = s.Text;
        }
        protected void Button1_Click(object sender, EventArgs e)
        {
            gen();
        }
    }

    I had placed a button and use it to trigger the Gen() method to generate some linked button.
    I had also created a Div, where the linked button should be placed to.


    Thanks in advance.


    2008年11月5日 上午 08:58
  • Could you share the aspx also?  In addition, just want to make sure you are in debug mode when monitoring the breakpoint and you are debugging the most updated version of your web form.

     

    I can get the following work fine in my environment:

     

    Default.aspx.cs

    Code Snippet

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;

    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            gen();
        }

        private void example(object sender, EventArgs e)
        {
            Label1.Text = ((LinkButton)sender).Text;
        }

        private void gen()
        {
            for (int i = 0; i < 10; i++)
            {
                LinkButton lb = new LinkButton();
                lb.Text = i.ToString();
                lb.Click += example;
                div_Paging.Controls.Add(lb);
            }
        }
    }

     

     

    Default.aspx

    Code Snippet

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

    <!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>
       
            <asp:ScriptManager ID="ScriptManager1" runat="server">
            </asp:ScriptManager>
            <asp:UpdatePanel ID="UpdatePanel1" runat="server">
                <ContentTemplate>
                    <asp:Label ID="Label1" runat="server" Text="0"></asp:Label>
                    <div runat="server" id="div_Paging">
                    </div>
                </ContentTemplate>
            </asp:UpdatePanel>
        </div>
        </form>
    </body>
    </html>

     

     

    2008年11月5日 上午 10:15
  • Hi Raymond,

     

    Thanks again, I am very appreciate for your instant reply = ).

    I think the difference between my code and you code is the linked button from my code is generate via a Button click event and your one is generate from the page load event.
    It works fine when I place the gen() function into the PageLoad event. I can debug the code as well.
    But i would like to make it load on-demand instead, as I will have 5 different grid view that, only want to generate the grid view went I need to.

    I am using VS2005, the masterpage I got contains the ScriptManager control

     

    example.aspx.cs

    Code Snippet

    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 main_example : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                LinkButton lb = new LinkButton();
                lb.Text = "1";
                lb.Click += example;
                div_Paging.Controls.Add(lb);
          
           }

           
        }

        private void gen()
        {
            for (int i = 0; i < 10; i++)
            {
                LinkButton lb = new LinkButton();
                lb.Text = i.ToString();
                lb.Click += example;
                div_Paging.Controls.Add(lb);
            }
        }

        private void example(object sender, EventArgs e)
        {
            LinkButton s = (LinkButton)sender;
            lbl_Err.Text = s.Text;
        }
        protected void Button1_Click(object sender, EventArgs e)
        {
            gen();
        }
    }

     

     


    example.aspx

    Code Snippet

    <%@ Page Language="C#" MasterPageFile="~/SiteMaster.master" AutoEventWireup="true" CodeFile="example.aspx.cs" Inherits="main_example" Title="Untitled Page" %>
    <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
    <asp:UpdatePanel runat="server" ID="update_P" UpdateMode="Conditional">
    <ContentTemplate >
    <div id="div_Paging" runat="server">
    </div>
    <asp:Label ID="lbl_Err" runat="server" />
        <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" />
    </ContentTemplate>
    </asp:UpdatePanel>
    </asp:Content>

     

     

     

    Once again, thank for your help.

    2008年11月5日 上午 11:03
  •  

    Try to think about the follow situation:

     

    For the first time you access the web page, your page will display 1 LinkButton (let's alias it as lb0 and this control has a event handler associated with it), 1 Label (with no text) and 1 Button.

     

    Then you click on the button and got a post back action.  At server side, Page_Load is being executed and now lb0 no longer exists because lb0 will only be created when the page is not pasted back.  After the Page_Load event handler finish, the Button1_Click event handler will be triggered which will create 10 LinkButtons and each of them will associated the click event to a event handler.  And now, the web page will be render back to the client browser which will show 10 LinkButtons, 1 Label (with no text) and 1 Button.

     

    At this point, you click on one of the LinkButton and this will trigger another post back action.  This time, the page object at server side will be created and contains the objects defined on the aspx, i.e. 1 Label and 1 Button only.  Page_Load event handler will be triggered at server side, and no more custom event handler will be executed.  It is because the LinkButtons do not exist before or during the Page_Load event (all custom event handlers will be executed after the Page_Load event).  Hence, the method/event handler "example" will not be executed!

     

    This is why you cannot make the expected result in your code sample.  If you would like to show the LinkButtons dynamically, I prefer to create all necessary controls on the aspx or during the Page_Load event.  Then use the Visible property to control the display status of those controls.

    2008年11月5日 下午 12:16
  • Hi Raymond,

    Thanks for your explanation.

    I do not think I can create all the necessary controls on the Page_Load event, as the record on Grid View is generated dynamically, depends on the parameter that user pass to it. which mean the number of page (linked button) will be different.

    If I put the code on Page_Load event it will load all the GridViews no matter which linked button i press? It may slow down the page as well, as it need to regenerate all the Linked Button (I had 5 different grid views on the same page, which is separated by a Tab Control).

    Do you have any suggestion that Even if I place all the function in to the page load event, but it will only execute the one I would like to execute?

    Is there any other way that I can work around that problem.

    Thanks in advance.
    2008年11月5日 下午 12:52
  • Putting the creation of controls in the Page_Load event doesn't mean that you have to retrieve all data from DB and populate onto the GridViews.  You can do the data retrieval and data binding depends on the state/event of your controls.  In addition, in your case, I would design a Web custom control to act as the GridView Pager so that I can reuse that for all 5 GridViews.  You may also try to think in this way.

     

    2008年11月5日 下午 05:44
  • Hi Raymond,

    Thanks very much for your suggestion. I am sorry, I am a bit dumb, not sure how to
    <<Putting the creation of controls in the Page_Load event doesn't mean that you have to retrieve all data from DB and populate onto the GridViews.  You can do the data retrieval and data binding depends on the state/event of your controls.>>

    About design a Custom Control, do you think I should create a ascx with a div and inside a div, i should automatically generate the linked button, something like that?

    Thanks very much for your help.

    2008年11月5日 下午 09:37