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

I am trying to write a simple webcontrol utility to display single-line messages inside a web page - status updates, error messages, etc. Messages will come from other controls on the page by calling a method in webcontrol. If the control does not have any messages by the time of its preliminary rendering, I do not want it to appear on the page at all - I want it to set Control.Visible = false. However, it seems that this only works for non-postback processing. Here is 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 with the same result too.

+7
source share
4 answers

Instead of changing the Visible property, try the following:

  protected override void Render(HtmlTextWriter writer) { if (queue.Count > 0) base.Render(writer); } 
+3
source share

I realized this myself, and I thought the answer would be useful to the community.

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

The solution is to reset control visibility in one of the previous events that are not skipped. The following change solved my problem:

 protected override void OnLoad(EventArgs e) { --> this.Visible = true; this.Controls.Clear(); base.OnLoad(e); } 
+5
source share

If you had code that should run on PreRender, even if the control is invisible (so setting Visible=true in OnLoad is not a solution), you can take advantage of the fact that the 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 applies to the possibility that the control parent (or other ancestor) is invisible. In this case, the OnPreRender control will not fire even if you make sure Visible = true in the control itself.

+2
source share

I suggest using OnInit instead:

 protected override void OnInit(EventArgs e) { base.OnInit(e); this.Visible = (queue.Count > 0); if (this.Visible) { while (queue.Count > 0) { MessageItem message = queue.Dequeue(); this.Controls.Add(new LiteralControl(message.ToString())); } } } 
0
source share

All Articles