3

If a "server-enabled" HTML tag is in a Web form, like this --

<p runat="server"/>

-- is there any way for me to attach to its rendering? I assume once they have runat="server", they must have a lifecycle of some kind.

I'd like to attach some code to the rendering of any HTML tag so enabled. So, whenever a template author puts runat="server" on a tag, I can catch the PreRender (or anything else) and execute some code.

Possible?

Deane
  • 8,269
  • 12
  • 58
  • 108
  • there is of course the OnPreRender which is attached to each control but that is for the developer of the control. I am not sure where/how you are wanting to attach to it? Do you think you can create some type of handler which is at the IIS level and inspects the page request or what? – phillip Dec 30 '10 at 14:29
  • I want to have some common code that runs on the PreRender of ANY server-enabled HTML tag. I don't want to have to attach it manually to each one. – Deane Dec 30 '10 at 14:35

3 Answers3

2

This is something done using adapters. You create one that does its magic, and associated it in a browser file contained in App_Browsers.

Here's an example of my experimental App_Browsers/Default.browser

<browsers>
  <browser refID="Default">
    <controlAdapters>
      <adapter controlType="System.Web.UI.HtmlControls.HtmlControl"
               adapterType="App_Code.Adapters.HtmlControlAdapter" />
    </controlAdapters>
  </browser>
</browsers>

And my adapter...

using System.Web.UI; using System.Web.UI.Adapters;

using System.Web.UI;
using System.Web.UI.Adapters;

namespace App_Code.Adapters {
    public class HtmlControlAdapter : ControlAdapter {
        protected override void Render(HtmlTextWriter writer) {
            writer.Write("<div style='background-color: #f00;'>");
            base.Render(writer);
            writer.Write("</div>");
        }
    }
}

My highly advanced adapter with superfragilicious abilities renders a div with inline styles around all controls deriving from HtmlControl (html-tags with runat="server", including <form runat="server">). Your adapter can hook into any event triggered by the control, so this should solve your needs.

sisve
  • 19,501
  • 3
  • 53
  • 95
0

Here is a link to the page lifecycle article. It's an important piece of information to know.

If you are coding it then you could create a class and override PreRender doing whatever you want inside it. Then your controls would implement that class.

If you prefer a more generic approach then you could do the same thing but at the page level. You could hook OnPreRender at the page level as such:

private void Page_PreRender(object sender, System.EventArgs e)
{
    Page page = sender as Page;
    if (page != null)
    {
        page.Controls.Clear(); // Or do whatever u want with ur page...
    }
}

private void InitializeComponent()
{    
    // Handle the Page.PreRender event.
    this.PreRender += new System.EventHandler(this.Page_PreRender);
}

That should give you the ability to check each control just before rendering.

phillip
  • 2,618
  • 19
  • 22
  • 1
    `InitializeComponent` isn't built-in method so you need to call it from somewhere, e.g. `Page_Load` so you need `AutoEventWireup=true` so you need just `Page_PreRender` without any implicit events subscription. – abatishchev Dec 30 '10 at 14:55
  • I believe that started in 3.5 but could be wrong... I gave you a point for the good info though. :) – phillip Dec 30 '10 at 15:01
0

I think this is what I'm looking for. It recursively iterates the entire control tree, and binds the event handler when it finds a HtmlControl.

protected override void OnLoad(System.EventArgs e)
{
    base.OnLoad(e);
    BindTagProcessor(Page);
}

private void BindTagProcessor(Control control)
{
    foreach (Control childControl in control.Controls)
    {
        if (childControl is HtmlControl)
        {
            ((HtmlControl)childControl).PreRender += new EventHandler(MyTagProcessor);                   
        }
        BindTagProcessor(childControl);
    }
}
Deane
  • 8,269
  • 12
  • 58
  • 108