我正在尝试编写一个简单的实用程序webcontrol来显示网页内的单行消息 - 状态更新,错误消息等。通过调用webcontrol上的方法,消息将来自页面上的其他控件。如果控件在预渲染时没有任何消息,我不希望它在页面上呈现 - 我希望它设置Control.Visible = false。这似乎只适用于非回发渲染。这是我正在使用的代码:
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
}
我也尝试将检查放在CreateChildControls中,结果相同。
答案 0 :(得分:5)
我实际上是自己想出来的,我认为答案对社区有用。
看起来像Control.Visible设置为false的控件实际上在Page_Load事件之后的某个时间停止。这里的技巧是将Control.Visible属性加载到ViewState中。因此,如果第一页上没有消息,则控件将自身设置为Visible = false,并且永远不会再次到达CreateChildControls或OnPreRender。
解决方案是重置控件在之前未跳过的事件中的可见性。以下更改解决了我的问题:
protected override void OnLoad(EventArgs e)
{
--> this.Visible = true;
this.Controls.Clear();
base.OnLoad(e);
}
答案 1 :(得分:3)
不要修改'Visible'属性,请尝试以下方法:
protected override void Render(HtmlTextWriter writer)
{
if (queue.Count > 0)
base.Render(writer);
}
答案 2 :(得分:2)
如果您的代码必须在PreRender上运行,即使控件不可见(因此在OnLoad中设置Visible=true
不是解决方案),您可以利用Page的PreRender事件将始终火。
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;
}
这也涉及控件的父(或其他祖先)不可见的可能性。在这种情况下,即使您确保控件本身的Visible = true,控件的OnPreRender也不会触发。
答案 3 :(得分:0)
我建议改用OnInit:
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()));
}
}
}