smithvoice.com
 Y'herd thisun? 

“I’m nauseatingly pro-American. It is where great things are possible.”

by Elon Musk

Webforms Inherited Panel control

TaggedCoding, CSharp, ASP.Net

Wasn't going to post this because some magic made the original problem go away, but just in case it comes back... my sitelett search makes it easier to find stuff than searching for commented out code :-).

Needed a container control for a Repeater's ItemTemplate so users could get the info from any collection of display controls (labels, images, whatever) and just click anywhere in the set for a serverside event instead of putting a button into the mix.

Easy enough, added an inherited Panel.  Worked fine as a drop-in on test pages but when added to the Repeater and was inline bound the doPostback javascript errored out on registration.  It was being rendered correctly in the html but when used in an ItemTemplate it didn't want to even get past page_load.

So I hand-wired the Render method to use the settimeout style and poof, it worked as a list item container.

Here's the server control code ClickyPanel.cs, note the commented out line in Render, being the traditional always-worked-before simple attribute style, followed by the verbose backslashed style that renders like non-submit controls set to AutoPostback.

 

using System;

namespace DemoControls
{
    public class ClickyPanel : System.Web.UI.WebControls.Panel, System.Web.UI.IPostBackEventHandler
    {
        public ClickyPanel() { }

        public event EventHandler Click;

        protected virtual void OnClick(EventArgs e)
        {
            if (Click != null)
            {
                Click(this, e);
            }

        }
   

        public void RaisePostBackEvent(string eventArgument)
        {
            OnClick(new EventArgs());
        }

        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {

            //this line is the tried and true... till I tried it this time in a repeater :(
            //this.Attributes.Add("onclick", "__doPostBack('" + this.UniqueID + "', '');");

            //this hokey escaped backslash style got the control past the javascript issues
            this.Attributes.Add("onclick", "javascript:setTimeout('__doPostBack(\\'" + this.UniqueID + "\\',\\'\\')', 0)");

            base.Render(writer);
        }
    }
}

 

Typical weirdness of coding, after I switched to the settimeout style and was all proud of myself, I reset and tested the traditional line again.  And all of a sudden it worked.  Dagnabbit.  I don't know, musta been some side effect but I swear those were the only lines I was mucking with.  Whatever. I'm keeping the settimeout style, but posting this here for my memory just in case. 

The after-nap update: aka DOH!

Figured out the root.  I forgot to add the __doPostback javascript to the page.  Guess when it was working it was because some other server control was on the page so the __doPostaback JS was being set but then I moved to a new page and mine was the first control added soooo, the engine didn't get any call to set it up. 

Dumb noob :).

Two ways to fix:

1) replace the this.Attributes.Add(... with a version that adds the JS if needed such as:

this.Attributes.Add("onclick", Page.ClientScript.GetPostBackEventReference(this, this.UniqueID));

2) because #1 will inject the standard non-settimeout version of the call code, if you want to keep the settimeout style and help avoid IE thread edge cases then keep your Attributes.Add line and follow it with this force of the postback support injection:

Page.ClientScript.GetPostBackEventReference(this, this.UniqueID);

And if you're using the custom panel (or any non-submit control set to AutoPostback) in a repeater that's being AJAXified remember to set the repeater's ClientIDMode to AutoID to force ASP.Net2 style control Ids or you'll get a full page postback due to the ASP.Net 4 default setting creating ids that don't include their full hierarchies.  MS recommends using the ScriptManager's RegisterAsyncPostbackControl during the repeater OnItemCreated event but I haven't been able to make that work on Alternating Items for some reason.  Some folks advise setting ClientIdMode AutoId at the page level and just being done with the edge cases, so if just doing it on the repeater doesn't work you may as well bulk up the whole page.

Sheesh.  20 years ago all I did was UI, then I fell in love with logic code.. now UI is back in my life and it is apparently pissed for my leaving it.  Muses, the things we have to do for their favors ;-)



home     who is smith    contact smith     rss feed π
Since 1997 a place for my stuff, and it if helps you too then all the better smithvoice.com