views:

118

answers:

2

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!

A: 

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.

Mehdi Golchin
Thanks for your reply! I'm a little confused by this... You're saying there's an easier way to do this? You're last sentence seems to indicate that. All I'm trying to do is make links trigger an ajax refresh instead of a full page refresh. Yes, clicking the links refresh other parts of the page.Also, I'm not sure why the CtlTest class above calls base(HtmlTextWriterTag.A)??? My WebControl has a series of links, not just one...
Dave
@Dave, you are right, it's my bad. The above code is just a simple example that illustrated how you can create a simple ajax enabled link button using 'ICallbackEventHandler' interface. As I mentioned above, IMO it's better to put your control in an update panel inseat of writing a full ajax enabled data pager control. Whereas you have to update a repeater control that associated to the data pager.
Mehdi Golchin
Hi Mehdi,My webcontrol is already inside an UpdatePanel but it still doesn't work. I actually figured it out... will Answer my Question next. Thanks for your help on this!
Dave
A: 

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!

Dave