I've built a class that derives from System.Web.UI.WebControl. It basically renders pagination links (same as what you see on top of GridView when enabled) for use above a repeater.

I'm creating some anchor tags explicitly inside my nav control obviously, but they don't perform ajax postbacks. My understanding is that ajax requires POSTS to work right? Well, these would be GETs which I think is the problem.

Is there a way to achieve what I'm trying to do?

Thanks!

2

There are 2 best solutions below

0
On

Ok, I figured it out. I simply made my class implement the IPostBackEventHandler. This makes your control fire an event when the user takes action on something. In my case, it's clicking a nav pagenumber: [1][2][3][4][5][Next >]

Then, inside my render where I create the Anchor tags, I add this to each href (pageStartRow is different for each):

PostBackOptions options = new PostBackOptions(this, pageStartRow.ToString()); writer.AddAttribute(HtmlTextWriterAttribute.Href, "javascript:" + Page.ClientScript.GetPostBackEventReference(options)); writer.RenderBeginTag(HtmlTextWriterTag.A);

The key is to pass something that uniquely identifies which link they clicked. This is done as the 2nd constructor parameter to the PostBackOptions class.

I then added the following items in my WebControl class:

// Defines the Click event. public delegate void ClickHandler(object sender, GridPagingNavClickedEventArgs e); public event ClickHandler Click;

//Invoke delegates registered with the Click event. protected virtual void OnClick(GridPagingNavClickedEventArgs e) { if (Click != null) { Click(this, e); } }

public void RaisePostBackEvent(string eventArgument) { GridPagingNavClickedEventArgs e = new GridPagingNavClickedEventArgs(Convert.ToInt32(eventArgument)); OnClick(e); }

The GridPagingNavClickedEventArgs contains a single item (pageNumber in my case).

Finally, in my aspx page (where I use the webcontrol), I do this in the Page_OnLoad:

gridNavTop.Click += new GridPagingNavigation.ClickHandler(gridNavTop_Click);

and this is the event code:

private void gridNavTop_Click(object sender, GridPagingNavClickedEventArgs e) { StartRow = e.PageStartRow; }

As long as everything is inside an UpdatePanel, then it works perfectly!

3
On

To take this advantage, you have to inherit the ICallbackEventHandler and implement its methods as follows.

public class CtlTest : WebControl, ICallbackEventHandler
{

    private static readonly object EventClick = new object();

    public CtlTest() : base(HtmlTextWriterTag.A) { }

    public event EventHandler Click
    {
        add { base.Events.AddHandler(EventClick, value); }
        remove { base.Events.RemoveHandler(EventClick, value); }
    }

    protected override void AddAttributesToRender(HtmlTextWriter writer)
    {
        base.AddAttributesToRender(writer);
        writer.AddAttribute(HtmlTextWriterAttribute.Href, "javascript:" + this.Page.ClientScript.GetCallbackEventReference(this, null, "null", null));
    }

    protected override void RenderContents(HtmlTextWriter writer)
    {
        base.RenderContents(writer);
        writer.Write("Submit Query");
    }

    protected virtual void OnClick(EventArgs e)
    {
        EventHandler handler = this.Events[EventClick] as EventHandler;
        if (handler != null)
            handler(this, e);
    }

    #region ICallbackEventHandler Members

    string ICallbackEventHandler.GetCallbackResult()
    {
        return string.Empty;
    }

    void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
    {
        this.OnClick(EventArgs.Empty);
    }

    #endregion

}

Whereas you are working on a data pager control and it requires to update some portions of the page, it's better to write a non Ajax enabled control and put it and its relative controls within an UpdatePanel.