Custom pagin template

kevinpang
Member since: 2008
 

Hi,

 I have a pagelist with paging turned on. I want to edit the rendered paging links. I know I can change the text for the last and first page link, but I want to get rid of the page numbers and replace with my own custom text. 

Does anyone know how to do this? As the paging footer/header template only adds to what's already there, not display in its place.

 

Thanks 

#19742 May 01, 2008 12:12
  • Tore Gjerdrum
    Member since: 2006
     

    Hi Kevin.

     I don`t think that is possible. But you can make your own paging control and that to the PageList like this PageList.PagingControl = customPager();

    Just use Reflector on the EPiServer.dll and you will find the PagingControl under EPiServer.Web.WebControls.PagingControl. You only need to override the CreatePagingItems(PageDataCollection pages).

    I have made my own pagingcontrol like this. Works like a charm :)

     BR,

    Tore 

    #19767 May 03, 2008 18:00
  • kevinpang
    Member since: 2008
     

    Hi, thanks for the tip, do you have a sample code you can post for me at all?

     

    thanks 

    #19798 May 06, 2008 13:38
  • Tore Gjerdrum
    Member since: 2006
     

    Hi Kevin.

    I have made a sample for you here. In the for loop, the page numbers are written out. You could either send you own text to AddSelectedPagingLink and the AddUnselectedPagingLink, or you can override them with you own code. Hope this helps you on your way :)

    <code>

    using System;
    using EPiServer.Core;
    using EPiServer.Web.WebControls;

    namespace EPiServerSample.Templates.WebControls
    {
    public class CustomEPiPager : PagingControl
    {
    // Fields
    private int _linkCounter;

    private string Translate(string text)
    {
    return LanguageManager.Instance.Translate("/webcontrols/paging/" + text);
    }

    public override void CreatePagingItems(PageDataCollection pages)
    {
    int pagingIndex = CurrentPagingItemCount - 1;
    bool visible = CurrentPagingItemIndex > 0;
    bool flag2 = CurrentPagingItemIndex < pagingIndex;
    if ((pagingIndex != 0) || !AutoPaging)
    {
    _linkCounter = 0;
    if (FirstPagingItemText.Length > 0)
    {
    AddUnselectedPagingLink(0, FirstPagingItemText, Translate("firstpage"), visible);
    AddLinkSpacing(visible);
    }
    if (PrevPagingItemText.Length > 0)
    {
    AddUnselectedPagingLink(CurrentPagingItemIndex - 1, PrevPagingItemText, Translate("prevpage"), visible);
    AddLinkSpacing(visible);
    }
    for (int i = 0; i <= pagingIndex; i++)
    {
    if (i == CurrentPagingItemIndex)
    {
    AddSelectedPagingLink(i, Convert.ToString((int)(i + 1)), Translate("currentpage"));
    }
    else
    {
    AddUnselectedPagingLink(i, Convert.ToString((int)(i + 1)), string.Format(Translate("pagenumber"), i + 1), true);
    }
    if (i < pagingIndex)
    {
    AddLinkSpacing();
    }
    }
    if (NextPagingItemText.Length > 0)
    {
    AddLinkSpacing(flag2);
    AddUnselectedPagingLink(CurrentPagingItemIndex + 1, NextPagingItemText, Translate("nextpage"), flag2);
    }
    if (LastPagingItemText.Length > 0)
    {
    AddLinkSpacing(flag2);
    AddUnselectedPagingLink(pagingIndex, LastPagingItemText, Translate("lastpage"), flag2);
    }
    }
    }
    }
    }

    </code> 

     

    Here is AddSelectedPageLink and AddUnselectedPageLink if you need them. Just include them in your CustomEPiPager class and override them.  

    <code>

    protected virtual LinkButton AddSelectedPagingLink(int pagingIndex, string text, string altText)
    {
    LinkButton child = this.CreatePagingLink(pagingIndex, text, altText);
    child.CssClass = CssClassSelected;
    Controls.Add(child);
    return child;
    }

    protected virtual LinkButton AddUnselectedPagingLink(int pagingIndex, string text, string altText, bool visible)
    {
    LinkButton child = this.CreatePagingLink(pagingIndex, text, altText);
    child.CssClass = CssClassUnselected;
    child.Visible = visible;
    Controls.Add(child);
    return child;
    }

    </code> 

    #19836 May 08, 2008 8:36
  • kevinpang
    Member since: 2008
     

    Hi,

    Thanks a lot for the code sample, it works great!

    Just one small issue. When the next page button is pressed, the page data doesn't actually move forward, it just triggers a postback and the data stays the same. Then on the 2nd press, it moves forward as expected.

    Is this a problem you've come across before?

    Also, at which event of the page is it best to assign the custom paging class to the pagelist? I currently do it on pageinit, is this correct?

    Thanks 

    #19872 May 12, 2008 11:20
  • kevinpang
    Member since: 2008
     
    #19873 May 12, 2008 11:22
  •  

    I've got the same problem
    I need to click 2 times to move to the next 10 pages in my pagelist

     Any soloutions?

     

    /jesper

    #20277 May 26, 2008 8:34
  • Tore Gjerdrum
    Member since: 2006
     
    Hi Kevin And Jesper.

    I tested it out and got the same problem. I am not sure why this propblem accours, but you could try overriding more of the source(EPiServer.Web.WebControls.PagingControl).

    I copied the whole code(EPiServer.Web.WebControls.PagingControl) from Reflector and got it to work. You should however just override the things you need. But this a way to start :)

    BR,

    Tore

    #20283 May 26, 2008 10:23
  •  

    Hmm ok
    I've copied all code from pagingControl  but get this error

    'EPiServer.Web.WebControls.PageListData' does not contain a definition for 'CurrentPagingItemIndex' 

     

    /jesper

    #20288 May 26, 2008 11:50
  • Tore Gjerdrum
    Member since: 2006
     

    Which version of EPiServer are you using? Try leaving out the CurrentPagingItemIndex property.

    <code>

      public virtual int CurrentPagingItemIndex
    {
    get
    {
    if (this._source == null)
    {
    return 0;
    }
    return this._source.CurrentPagingItemIndex;
    }
    set
    {
    this._source.CurrentPagingItemIndex = value;
    }
    }

    </code> 

     

    Tore 

    #20290 May 26, 2008 12:13
  •  

    I need CurrentPagingItemIndex to when I call the PagingItemChanged

    I think my problem is the 'Source'

    I set the pagingControl like this

    PagingControl customPaging = new epiPager();
    NewsPageList.PagingControl = customPaging;

    Should I define the the dataSource for customPaging?

    /jesper 

    #20296 May 26, 2008 13:18
  • Tore Gjerdrum
    Member since: 2006
     

    Hi Jesper.

    But you will have access to the CurrentPagingItemIndex via the PagingControl class that you inherit from. I skipped the public virtual int CurrentPagingItemIndex, and it worked fine for me.

    PageList.PagingControl = new epiPager(); should be fine.

     

     BR,

    Tore 

    #20299 May 26, 2008 14:00
  •  

    Hmm yes...

    but when I do I get "System.NullReferenceException: Object reference not set to an instance of an object" on this line: this.CurrentPagingItemIndex = num; 

    in PagingItemChanged

     

    /jesper

     

    #20301 May 26, 2008 14:34
  • Tore Gjerdrum
    Member since: 2006
     

    Hi Jesper.

    Try to not override PagingItemChanged. As I said in my post earlier today, you should just override the things you need to override. So try to remove things one by one. I don`t think you need to override all the properties, but I have not had the time to try it out myself.

     

    BR,

    Tore 

    #20303 May 26, 2008 14:44
  •  

    Hi Tore,
    Thanx for your time
    I've tried to remove allmost everything but I get null reference error

    I'm starting to think that  I've done something wrong in the start of my code

    My code starts like this:

    <code>

    namespace hk.templates.WebControls
    {
        public class epiPager : PagingControl
       {

        // Fields
        private int _linkCounter;
        private PageListData _source;

    // Methods

        public epiPager()

       {

        }

       public epiPager(PageListData source)
       : this()
       {
           this._source = source;
           this._linkCounter = 0;
        }
    </code>

    It's not the same start as my customEpipager control I've made that works
    Am I doing this wrong?

    best regards

    jesper 

     

    #20310 May 27, 2008 8:27
  • Tore Gjerdrum
    Member since: 2006
     

    Hi Jesper.

     I have made a new pager that not use postbacks at all and sets the CurrentPagingItemIndex by a querystring parameter. It also renders out <ul><li><ol> elements. I have tested this and it shoud work :)

    Code for Pager: 

    <code>

    using System;
    using System.Text;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;
    using EPiServer;
    using EPiServer.Core;
    using EPiServer.Web.WebControls;

    namespace Hlf.Templates.WebControls
    {
    public class Pager : PagingControl
    {
    // Private variables
    private int controlCount;

    // Methods
    private static string translate(string text1)
    {
    return LanguageManager.Instance.Translate("/webcontrols/paging/" + text1);
    }

    private HtmlGenericControl linkButton(int num1, string text1, string text2)
    {
    HtmlGenericControl control = new HtmlGenericControl("a");
    controlCount++;
    control.Attributes.Add("href", GetUrl(num1));
    control.InnerText = text1;
    control.Attributes.Add("title", text2);

    return control;
    }

    private static string GetUrl(int count)
    {
    UrlBuilder url = new UrlBuilder(HttpContext.Current.Request.Url);
    EPiServer.Global.UrlRewriteProvider.ConvertToExternal(url, null, UTF8Encoding.UTF8);
    return UriSupport.AddQueryString(url.ToString(), "p", count.ToString());
    }

    private static HtmlGenericControl spancontrol(int num1, string text1, string text2)
    {
    HtmlGenericControl control = new HtmlGenericControl("span");
    control.InnerText = text1;
    control.Attributes.Add("title", text2);
    return control;
    }

    protected static HtmlGenericControl AddSelectedPagingLink(int pagingIndex, string text, string altText, ControlCollection controls)
    {
    HtmlGenericControl child = new HtmlGenericControl("li");
    HtmlGenericControl innerchild = spancontrol(pagingIndex, text, altText);
    child.Controls.Add(innerchild);
    controls.Add(child);
    return child;
    }

    protected new HtmlGenericControl AddSelectedPagingLink(int pagingIndex, string text, string altText)
    {
    return AddSelectedPagingLink(pagingIndex, text, altText, Controls);
    }

    protected HtmlGenericControl AddUnselectedPagingLink(int pagingIndex, string text, string altText, bool visible, string span, ControlCollection controls)
    {
    HtmlGenericControl child;

    if (!visible && span == "prev")
    {
    child = new HtmlGenericControl("li");
    child.Attributes.Add("class", "prev");
    HtmlGenericControl innerchild = spancontrol(pagingIndex, text, altText);
    child.Controls.Add(innerchild);
    controls.Add(child);
    }

    else if (visible && span == "prev")
    {
    child = new HtmlGenericControl("li");
    child.Attributes.Add("class", "prev");
    HtmlGenericControl innerchild = linkButton(pagingIndex, text, altText);
    child.Controls.Add(innerchild);
    controls.Add(child);
    }

    else if (!visible && span == "next")
    {
    child = new HtmlGenericControl("li");
    child.Attributes.Add("class", "next");
    HtmlGenericControl innerchild = spancontrol(pagingIndex, text, altText);
    child.Controls.Add(innerchild);
    controls.Add(child);
    }

    else if (visible && span == "next")
    {
    child = new HtmlGenericControl("li");
    child.Attributes.Add("class", "next");
    HtmlGenericControl innerchild = linkButton(pagingIndex, text, altText);
    child.Controls.Add(innerchild);
    controls.Add(child);
    }

    else
    {
    child = new HtmlGenericControl("li");
    HtmlGenericControl innerchild = linkButton(pagingIndex, text, altText);
    child.Controls.Add(innerchild);
    controls.Add(child);
    }

    return child;
    }

    protected HtmlGenericControl AddUnselectedPagingLink(int pagingIndex, string text, string altText, bool visible, string span)
    {
    return AddUnselectedPagingLink(pagingIndex, text, altText, visible, span, Controls);
    }

    public override void CreatePagingItems(PageDataCollection pages)
    {
    int pagingIndex = CurrentPagingItemCount - 1;
    bool visible = CurrentPagingItemIndex > 0;
    bool flag2 = CurrentPagingItemIndex < pagingIndex;

    if ((pagingIndex != 0) || !AutoPaging)
    {
    HtmlGenericControl ul = new HtmlGenericControl("ul");
    if (CssClassPagingContainer != null && CssClassPagingContainer.Length > 0)
    ul.Attributes.Add("class", CssClassPagingContainer);

    controlCount = 0;
    if (FirstPagingItemText.Length > 0)
    AddUnselectedPagingLink(0, FirstPagingItemText, translate("firstpage"), visible, string.Empty, ul.Controls);

    if (PrevPagingItemText.Length > 0)
    {
    string prev = "prev";
    AddUnselectedPagingLink(CurrentPagingItemIndex - 1, PrevPagingItemText, translate("prevpage"), visible, prev,
    ul.Controls);
    }

    HtmlGenericControl li = new HtmlGenericControl("li");
    HtmlGenericControl ol = new HtmlGenericControl("ol");

    for (int i = 0; i <= pagingIndex; i++)
    {
    if (i == CurrentPagingItemIndex)
    AddSelectedPagingLink(i, Convert.ToString(i + 1), translate("currentpage"), ol.Controls);

    else
    AddUnselectedPagingLink(i, Convert.ToString(i + 1), string.Format(translate("pagenumber"), i + 1), true,
    string.Empty, ol.Controls);
    }

    li.Controls.Add(ol);
    ul.Controls.Add(li);

    if (NextPagingItemText.Length > 0)
    {
    string next = "next";
    AddUnselectedPagingLink(CurrentPagingItemIndex + 1, NextPagingItemText, translate("nextpage"), flag2, next,
    ul.Controls);
    }

    if (LastPagingItemText.Length > 0)
    AddUnselectedPagingLink(pagingIndex, LastPagingItemText, translate("lastpage"), flag2, string.Empty, ul.Controls);

    Controls.Add(ul);
    }
    }

    public override Control CreatePagingContainer()
    {
    PlaceHolder placeholder = new PlaceHolder();
    return placeholder;
    }

    public override string NextPagingItemText
    {
    get { return ((ViewState["NextPagingItemText"] == null) ? translate("nextpage") : ((string)ViewState["NextPagingItemText"])); }
    set { ViewState["NextPagingItemText"] = value; }
    }

    public override string PrevPagingItemText
    {
    get { return ((ViewState["PrevPagingItemText"] == null) ? translate("prevpage") : ((string)ViewState["PrevPagingItemText"])); }
    set { ViewState["PrevPagingItemText"] = value; }
    }

    public override string FirstPagingItemText
    {
    get { return ((ViewState["FirstPagingItemText"] == null) ? translate("firstpage") : ((string)ViewState["FirstPagingItemText"])); }
    set { ViewState["FirstPagingItemText"] = value; }
    }

    public override string LastPagingItemText
    {
    get { return ((ViewState["LastPagingItemText"] == null) ? translate("lastpage") : ((string)ViewState["LastPagingItemText"])); }
    set { ViewState["LastPagingItemText"] = value; }
    }

    public override string CssClassPagingContainer
    {
    get { return ((ViewState["CssClassPagingContainer"] == null) ? string.Empty : ((string)ViewState["CssClassPagingContainer"])); }
    set { ViewState["CssClassPagingContainer"] = value; }
    }
    }
    }

     

    </code>

     

    Code for getting the querystring parameter

    <code>

     ///
    /// Gets the CurrentPagingItemIndex from the QueryString
    ///
    /// The CurrentPagingItemIndex. If it doesn't exist, 0 is returned
    protected static int GetItemIndex()
    {
    int num;
    return ((HttpContext.Current.Request.QueryString["p"] != null) && (int.TryParse(HttpContext.Current.Request.QueryString["p"], out num))) ? num : 0;
    }

    </code>

     

    Code for setting the pager on the list

    <code>

     PageList.PagingControl = new Pager();
    PageList.PagesPerPagingItem = (int)CurrentPage["ListCount"];
    PageListList.PagingControl.CurrentPagingItemIndex = GetItemIndex(); PageList.PagingControl.FirstPagingItemText = "";
    PageList.PagingControl.LastPagingItemText = ""; plList.PagingControl.CssClassPagingContainer = "pager";

    </code>

     

    Hope this solves your problem :)

     

    BR,

    Tore 

    #20333 May 27, 2008 11:40
  •  

    IT works great!!

    thank you!

     

     

    #20336 May 27, 2008 13:49
  • kevinpang
    Member since: 2008
     
    I haven't worked on this problem for a bit, but been discussing this with a colleague, and he thinks it might be a viewstate problem. In which case, the control needs to be overridden at a later stage in the page cycle. Will try that when I work on this again.
    #20483 Jun 02, 2008 14:56
  • Tony Gayter
    Member since: 2008
     
    Has anyone figured out what the issue is with this double click problem? I hav ecreated my custom pager and it all works perfectly with the exception of the double click? Its really annoying me as I have tried everything I can think of.
    #20645 Jun 06, 2008 18:19
  • Tore Gjerdrum
    Member since: 2006
     

    Hi Tony.

    I am not sure why this happes. There got to be something we are forgetting to do. Maybe we should contact EPiServer and get them to look at it?

    But if you look at the last example I have pasted in you will get a working custom pager :)

     

    BR,

    Tore 

    #20648 Jun 08, 2008 17:32
  • Tony Gayter
    Member since: 2008
     

    Unfortunatly that woul dmean I would not be able to use it in an ajax update panel as it wouldnt catch the postback to update.

    #20776 Jun 11, 2008 17:46
  • daro
    Member since: 2007
     
    This issue has now been reported in our system with the following description.
    #11236: Overriding the method PagingControl.CreatePagingItems will cause a double click issue
    #20916 Jun 17, 2008 14:34
  • kevinpang
    Member since: 2008
     
    Does anyone know how to make the pager appear on top as well as below a pagelist?
    #20947 Jun 17, 2008 15:40
  • Tore Gjerdrum
    Member since: 2006
     

    Hi Kevin.

     I do not think this is possible. But you could make your own CustomPageList that inhertits from PageList. Make your own ITemplates called HeaderPagingHeader and HeaderPagingFooter. Then override the CreateChildControls() and render out these  ITemplates before the ItemTemplate. Maybe you have to do something in PageListData.CreatePagingControls() to say that you want the pager rendered out in the new ITemplates as well as PagingHeaderTemplate and PagingFooterTemplate.

     

    BR,

    Tore 

    #20954 Jun 18, 2008 8:25
  • kevinpang
    Member since: 2008
     

    Worked out a great way to display the pager on top as well as below the pagelist.

     

    You just need to implement the Pagelist prerender event like this:

     

     protected void SearchResult_PreRender(object sender, EventArgs e)
    {
        PageList pageList = (PageList)sender;

        StringBuilder builder = new System.Text.StringBuilder();
        StringWriter stringWriter = new StringWriter(builder);
        HtmlTextWriter writer = new HtmlTextWriter(stringWriter);
        pageList.PagingControl.RenderControl(writer);
        string html = builder.ToString();
        litTopPager.Text = html; //Literal control placed anywhere on the page.

    }

     

    Then, most importantly, you need to override an event on the Page base class like this:

     public override void VerifyRenderingInServerForm(System.Web.UI.Control control)
    {

    }

     

    I've implemented a baseclass that inherits from the EpiServer template class, andput this there.

    What it does is overrides the validation error caused  by the pagerender when you have a server control and it's not inside a form tag. 

     

     

    #21294 Jun 25, 2008 15:20
  • Björn Lennartsson
    Member since: 2007
     

    Hi,

    I needed a similar solution and found this nice little thread. I used Tore's first class but made some modifications to solve the double-click problem. 

    The problem occures because the variable _linkCounter is declared as private in the base class. When we don't override the rest of the methods that use this variable it won't work since the methods all use this._linkCounter.

    If you use the code that Tore posted and only add the following three sections it will work perfectly. 

    protected override LinkButton AddSelectedPagingLink(int pagingIndex, string text, string altText)
    {
    LinkButton child = this.CreatePagingLink(pagingIndex, text, altText);
    child.CssClass = this.CssClassSelected;
    this.Controls.Add(child);
    return child;
    }

    protected override LinkButton AddUnselectedPagingLink(int pagingIndex, string text, string altText, bool visible)
    {
    LinkButton child = this.CreatePagingLink(pagingIndex, text, altText);
    child.CssClass = this.CssClassUnselected;
    child.Visible = visible;
    this.Controls.Add(child);
    return child;
    }

    private LinkButton CreatePagingLink(int pagingIndex, string text, string altText)
    {
    LinkButton button = new LinkButton();
    this._linkCounter++;
    button.ID = "PagingID" + this._linkCounter.ToString();
    button.CommandName = pagingIndex.ToString();
    button.Command += new CommandEventHandler(this.PagingItemChanged);
    button.Text = text;
    button.Attributes.Add("title", altText);
    return button;
    }
     
    Best regards,
    #21591 Edited, Jul 02, 2008 9:44
  •  

    Hi,

     I tried to use Kevin Pangs solution (since it seemed to be the most simple) , but I get a null reference error and as far as I can see thevariable "builder" is empty. Where do you assign a value to it? 

    //Pontus

    #30312 Jun 11, 2009 12:43
  •  

    Sorry, my mistake, I dind't read the code properly. It works now, thanks.

     /P

    #30335 Jun 11, 2009 17:02