views:

390

answers:

2

I have a Custom Repeater control that inherits from Repeater and has paging functionality, however when I click the next page button the first time it refreshes the control but does not change the page, if I click it again after that it changes page perfectly.

I know what the issue is, when I click the next button it does a postback, then the data is bound to the repeater, and then after that the NextButton Event is handled.

Is there any way I can change the order of the page load events?? Or force the repeater to reload again after the event is handled??

I've included my Custom Repeater class bellow:

using System.Web.UI.WebControls;
using System.Web.UI;
using System.Data;
using System.Collections;
using System;

namespace ASPresentation.Controls
{
[ToolboxData("<cc:PagedRepeater runat=server></cc:PagedRepeater>")]
public class PagedRepeater : Repeater
{
    public int PageSize { get; set; }
    public int CurrentPageIndex
    {
        get
        {
            return Convert.ToInt16(Page.Session["ProjectIndex"]);
        }
        set
        {
            Page.Session.Add("ProjectIndex", value);
        }
    }
    public PagedDataSource pagedData = new PagedDataSource();
    LinkButton NextBtn = new LinkButton();
    LinkButton PrevBtn = new LinkButton();

    public bool IsLastPage
    {
        get
        {
            return pagedData.IsLastPage;
        }
    }
    public bool IsFirstPage
    {
        get
        {
            return pagedData.IsFirstPage;
        }
    }

    public override object DataSource
    {
        get
        {
            return base.DataSource;
        }
        set
        {
            pagedData.DataSource = (IEnumerable)value;
        }
    }

    protected void NextButtonClick(object sender, EventArgs e)
    {
        if (!IsLastPage)
        {
            CurrentPageIndex++;
        }
    }

    protected void PrevButtonClick(object sender, EventArgs e)
    {
        if (!IsFirstPage)
        {
            CurrentPageIndex--;
        }
    }

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        NextBtn.Text = "Next";
        PrevBtn.Text = "Prev";
        NextBtn.Click += new EventHandler(NextButtonClick);
        PrevBtn.Click += new EventHandler(PrevButtonClick);
    }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        base.Controls.Add(PrevBtn);
        base.Controls.Add(NextBtn);
    }

    protected override void Render(HtmlTextWriter writer)
    {
        base.Render(writer);
    }

    public override void DataBind()
    {
        pagedData.AllowPaging = true;
        pagedData.PageSize = PageSize;
        pagedData.CurrentPageIndex = CurrentPageIndex;
        base.DataSource = pagedData;
        base.DataBind();
    }
}
}
A: 

Call "this.DataBind()" in the Page change functions.

This will mean you databind twice when changing pages but will work :-\

TJMonk15
I tried that, it made my buttons disapear, Probably because it was re rendering without first doing init and load where the buttons are added.
Morgeh
A: 

A couple issues here that jump out at me.

One, why are you dynamically creating the prev/next button? Just put them in the ASCX. Show/hide them if you like based on whether your page index is first/last. If you must create them dynamically, do so in Init...

Two, do not store your page index in the session like that. What happens when you have two of these custom repeaters on one page? Use the ViewState. Key the string name to the control ID if necessary, but I think ViewState does this automatically(?).

Finally, what is triggering the DataBind? What event handler? It must be called from the Page that is hosting this control. If that's the case, then you also need to expose the Next/Prev clicks as events so that DataBind can be called in response to these events. This is how Microsoft's controls that handle paging work, such as the GridView. NextBtn.Click or PrevBtn.Click is guaranteed to be the last postback event handled.

You could handle the next/prev internally, but if you're going to do that you need to also call DataBind() in your code, so that it happens at the correct time.

Bryan