我正在为使用HTML4.0和IIS7的客户端构建一个数据库编辑器/业务流程工具。我希望根据存储在会话中的值,有条件地在我的页面中包含一些.NET。我在服务器端这样做,为了封装代码,我创建了一个ASP服务器控件。
正如您将看到的,由服务器控件生成的标记并不是我所期望的。我希望有人之前已经看到了这一点,可以帮助我理解如何控制标记生成输出。
这是一个名为MyList的控件的新RenderContents。它应该使用标签生成新的列表条目。
protected override void RenderContents(HtmlTextWriter output) {
output.RenderBeginTag(HtmlTextWriterTag.Li);
output.WriteEncodedText(this.Text);
output.RenderEndTag();
}在编译了主项目并添加了对MyList的引用后,我在下面的HTML中使用了MyList:
<h1>Favorite Things</h1>
<ul>
<cc1:MyList ID="mL1" runat="server" Text="Code that works!" />
<cc1:MyList ID="mL2" runat="server" Text="Going home before 8" />
<cc1:MyList ID="mL3" runat="server" Text="Cold drinks in fridge" />
</ul>它会生成以下代码:
<h1>Favorite Things</h1>
<ul>
<span id="MainContent_mL1"><li>Code that works!</li></span>
<span id="MainContent_mL2"><li>Going home before 8</li></span>
<span id="MainContent_mL3"><li>Cold drinks in fridge</li></span>
</ul>现在,我添加一个基于会话值的测试。WebControl的Page属性为我提供了对控件容器的引用,从而访问我的会话:
protected override void RenderContents(HtmlTextWriter output) {
string backcolor = "Yellow";
if (this.Page.Session["access"] == null) {
backcolor = "Red";
}
output.RenderBeginTag(HtmlTextWriterTag.Li);
output.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, backcolor);
output.WriteEncodedText(this.Text);
output.RenderEndTag();
}现在标记开始解开了。注意‘ml1’中的不一致:
<h1>Favorite Things</h1>
<ul>
<span id="MainContent_mL1"><li>Code that works!</li></span>
<span id="MainContent_mL2" style="background-color:Red;"><li>Going home before 8</li></span>
<span id="MainContent_mL3" style="background-color:Red;"><li>Cold drinks in fridge</li></span>
</ul>在我的实际代码中,它更复杂,标记只变成了span标记。而且,当我在RenderContents()中设置断点时,当我有五个连续的标签时,它只被调用一次。
其他信息:带有cc1:MyList控件的页面有EnableSession=true。我的web.config指定了正常的会话管理器('rml','RoleBasedList‘指的是我的’真正‘控制,我简化了这个控制,以隔离问题并使本文更简短):
<system.web>
<trace enabled="true" localOnly="false" pageOutput="true" requestLimit="20" />
<compilation debug="true" targetFramework="4.0" />
<pages>
<controls>
<add tagPrefix="rml" assembly="RoleBasedList" namespace="SOTS.ServerControls"/>
</controls>
</pages>
<httpModules>
<add name="Session" type="System.Web.SessionState.SessionStateModule"/>
</httpModules>
<sessionState mode="InProc" cookieless="false" timeout="60"/>
...
</system.web>现在你知道我做的一切了!
发布于 2012-09-23 01:50:06
您只需覆盖自定义服务器控件中的WebControl.TagKey属性:
protected override HtmlTextWriterTag TagKey
{
get { return HtmlTextWriterTag.Li; }
}默认值为Span,它解释了您所看到的内容。当然,如果这样做,就不会在RenderContents覆盖中呈现Li标记。
另一种方法是覆盖Render,完全控制渲染,或者从Control派生。但是您将失去WebControl的一些特性,特别是外部标记的样式。
关于您的第二个问题,您正在调用:
output.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, backcolor);这将添加一个样式属性,该属性将应用于下一次对RenderBeginTag的调用。您不会调用RenderBeginTag,因此这将应用于树中下一个控件中的标记。
另一点是,当您的控件在Visual Studio designer中呈现时,Session将为空。您应该检查是否为null,或者检查您是否在设计模式下运行:
if ((Site != null) && (Site.DesignMode))
{
... running in design mode, Session won't be available
}发布于 2012-09-22 22:31:26
避免使用System.Web.UI.WebControls。我建议你直接继承System.Web.UI.Control的子类。
<span>是由您从中派生的类插入的(您还没有提到)。注意,您覆盖的是RenderContents而不是Render,这意味着控件超类可以自由地用它想要的任何东西包装RenderContents的输出,在本例中是<span>。
https://stackoverflow.com/questions/12540658
复制相似问题