Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

At what point in the control life cycle does Control.Visible stop rendering?

Tags:

c#

asp.net

I am trying to write a simple utility webcontrol to display one-line messages inside a web page - status updates, error messages, etc. The messages will come from other controls on the page, by calling a method on the webcontrol. If the control doesn't have any messages by the time it gets to pre-render, I don't want it to render on the page at all - I want it to set Control.Visible = false. This only seems to work for non-postback rendering though. Here's the code I'm using:

public class MessageList : WebControl
{

#region inner classes

    private struct MessageItem
    {
        string Content, CssClass;

        public MessageItem(string content, string cssClass)
        {
            Content = content;
            CssClass = cssClass;
        }

        public override string ToString()
        { return "<li" + (String.IsNullOrEmpty(CssClass) ? String.Empty : " class='" + CssClass + "'") + ">" + Content + "</li>"; }
    }

    private class MessageQueue : Queue<MessageItem> { }

#endregion

#region fields, constructors, and events

    MessageQueue queue;

    public MessageList() : base(HtmlTextWriterTag.Ul)
    {
        queue = new MessageQueue();
    }

    protected override void OnLoad(EventArgs e)
    {
        this.Controls.Clear();
        base.OnLoad(e);
    }

    protected override void OnPreRender(EventArgs e)
    {
        this.Visible = (queue.Count > 0);

        if (this.Visible)
        {
            while (queue.Count > 0)
            {
                MessageItem message = queue.Dequeue();
                this.Controls.Add(new LiteralControl(message.ToString()));
            }
        }

        base.OnPreRender(e);
    }

#endregion

#region properties and methods

    public void AddMessage(string content, string cssClass)
    { queue.Enqueue(new MessageItem(content, cssClass)); }

    public void AddMessage(string content)
    { AddMessage(content, String.Empty); }

#endregion

}

I tried putting the check inside CreateChildControls too, with the same result.

like image 469
The Digital Gabeg Avatar asked Oct 21 '09 01:10

The Digital Gabeg


3 Answers

I actually figured this out myself, and I thought the answer would be useful to the community.

It looks like a control which has Control.Visible set to false actually stops sometime after the Page_Load event. The trick here is that the Control.Visible property is loaded into ViewState. So if there are no messages on the first page hit, then the control sets itself to Visible = false, and never again reaches either CreateChildControls or OnPreRender.

The solution is to reset the control's visibility in one of the earlier events which aren't skipped. The following change solved my problem:

protected override void OnLoad(EventArgs e)
{
--> this.Visible = true;
    this.Controls.Clear();
    base.OnLoad(e);
}
like image 178
The Digital Gabeg Avatar answered Sep 28 '22 13:09

The Digital Gabeg


Instead of modifying the 'Visible' property, try this :

    protected override void Render(HtmlTextWriter writer)
    {
        if (queue.Count > 0)
            base.Render(writer);
    }
like image 29
Manitra Andriamitondra Avatar answered Sep 28 '22 13:09

Manitra Andriamitondra


If you had code that must run on PreRender even if the control is invisible (so that setting Visible=true in OnLoad isn't a solution), you could take advantage of the fact that the Page's PreRender event will always fire.

protected void AlwaysPreRender( object sender, EventArgs e )
{
    if ( /* some condition */ )
    {
        this.Visible = true;
    }
    // else leave Visible as it was
}

protected override void OnLoad(EventArgs e)
{
    Page.PreRender += this.AlwaysPreRender;
}

This also deals with the possibility that the control's parent (or other ancestor) is invisible. In this case, the control's OnPreRender won't fire even if you ensure that Visible=true on the control itself.

like image 43
stevemegson Avatar answered Sep 28 '22 12:09

stevemegson