ASP.NET - 将自定义CompositeControl渲染为String?

时间:2009-03-30 21:57:16

标签: asp.net controls

我正在尝试将复合控件呈现给字符串并将其写入页面:

Dim sb As New StringBuilder
Dim sw As New StringWriter(sb)
Dim hw As New HtmlTextWriter(sw)
Dim CustomCompositeControl as New MyCustomCompositeControl
CustomCompositeControl.RenderControl(hw)
HttpContext.Current.Response.Write(sb.ToString)

不幸的是,它只是渲染一个空的span标记。

甚至可以像在DataGrid中那样将CompositeControls渲染为字符串吗?

没有进入我的CompositeControl的文字内部,在通过RenderControl渲染之前,我应该在CompositeControl中确定一些内容吗?

注意:我没有覆盖CompositeControl中的RenderControl。我需要这样做吗?

更新 好。我有点想通了。我必须确保在RenderControl方法运行之前调用CompositeControl的EnsureChildControls方法。我不太确定在内部调用它的最佳位置。

3 个答案:

答案 0 :(得分:2)

如果您有权访问简单地调用Render()方法,只需这样做,它将为您提供您正在寻找的结果。否则,是的,您将不得不重写RenderControl()...取决于您何时调用它,您可以通过调用Render()方法内部RenderControl()来逃脱。

另外,您应该注意复合控件的顶级html标记始终是一个span,除非您将其指定为其他内容,例如div:

/// <summary>
/// Render as div instead of the default span.
/// </summary>
/// <value></value>
/// <returns>HtmlTextWriterTag.Div</returns>
protected override HtmlTextWriterTag TagKey
{
   get
   {
      return HtmlTextWriterTag.Div;
   }
}

答案 1 :(得分:1)

是的,这是可能的,但是如果不了解控件内部及其对asp.net生命周期内各种事件的依赖性,是否可能?我不认为这是可能的。

例如,一个DataGrid可能依赖于在一个表单中,我的猜测是它会出错,表明没有表单。

答案 2 :(得分:0)

看看这个MSDN page discussing CompositeControls,特别是标题为“复合控件的渲染引擎”的部分

  

请求处理   代码(在Page类中)调用   EnsureChildControls之前   将PreRender事件触发到页面   和每个孩子控制。

在正常的ASP.NET请求期间,您在CompositeControl中覆盖的CreateChildControls()方法直到它到达请求生命周期的后期才会被调用,就在PreRender之前。如果您尝试在正常的ASP.NET页面生命周期之外渲染CompositeControl,则永远不会添加子控件,因为不会调用任何子控件创建方法。保证在手动渲染控件时调用EnsureChildControls()的最佳方法是覆盖RenderControl(),如下所示:

public override void RenderControl(HtmlTextWriter writer)
{
    // We must explicitly call EnsureChildControls() in cases where we are rendering 
    // a CompositeControl outside of the normal ASP.NET page lifecycle
    EnsureChildControls();
    base.RenderControl(writer);
}

对我来说,CompositeControl类本身并没有以类似的方式覆盖RenderControl()方法,这似乎很奇怪。如果你使用Reflector来检查CompositeControl的实现细节,你会发现在类中重写的所有方法都只是为了调用EnsureChildControls();如果控件处于设计模式,甚至Render()也会调用EnsureChildControls()方法。来自Reflector:

protected internal override void Render(HtmlTextWriter writer)
{
    if (base.DesignMode)
    {
        this.EnsureChildControls();
    }
    base.Render(writer);
}