【问题标题】:Render .net controls to string and get events to fire将 .net 控件渲染为字符串并触发事件
【发布时间】:2011-07-28 20:26:47
【问题描述】:

我有这个问题,我正在尝试生成 HTML 以显示在来自数据库的页面上,该页面以模板的形式显示,该模板具有不同的大括号,在运行时被动态内容替换。例如,花括号 {Content} 被一些复选框列表、单选按钮列表、文本框和提交按钮替换。我这样做的方式是动态创建控件并将它们呈现为字符串,然后将该字符串输出到浏览器。但这所做的是,它在生成控件时无法识别分配给控件的事件。我可能对这个问题采取了错误的方法,但我真的不知道如何实现这一点。我在下面提供了一些示例代码来展示我想要实现的目标。请告知如何解决此问题。

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    If Not IsPostBack Then

        Dim PageContent As StringBuilder = New StringBuilder()
        PageContent.Append("A lot of content from database laid out using HTML templates stored in database including the below mentioned button code.")

        '# To illustrate how pagecontent is built using lots of such controls rendered to string
        Dim SubmitButton As Button = New Button()
        SubmitButton.ID = "MySubmitButton"
        SubmitButton.Text = "Submit"
        SubmitButton.CssClass = "SubmitButton"
        'Page.Controls.Add(SubmitButton)        '# This line I thought would resolve the issue, but it doesn't as the .net form is not built at the time of page load
        AddHandler SubmitButton.Click, AddressOf ClickHandler

        PageContent.Append(RenderControlToString(SubmitButton))

        Dim Output As Literal = New Literal()
        Output.Text = PageContent.ToString()
        Page.Controls.Add(Output)

    End If

End Sub

''' <summary>
''' Button Click Hander
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub ClickHandler(ByVal sender As System.Object, ByVal e As System.EventArgs)

    '# Control never gets here!!!!!
    Response.Write("<br/>Button Clicked!")
    Response.End()

End Sub

''' <summary>
''' Render control to string
''' </summary>
''' <param name="control"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Function RenderControlToString(control As Control) As String

    Dim sb = New StringBuilder()
    Using sw = New StringWriter(sb)
        Using textWriter = New HtmlTextWriter(sw)
            control.RenderControl(textWriter)
        End Using
    End Using

    Return sb.ToString()

End Function

感谢您的建议!

【问题讨论】:

    标签: .net asp.net vb.net webforms


    【解决方案1】:

    在 .Net 中动态加载控件有点令人困惑。我看到你正在做的四个问题。

    1. 您正在尝试仅在初始 HTTP GET(而不是回发)上动态添加控件。您需要每次都添加控件。您不是在此处绑定数据,而是向 Page 控件树中添加控件。每次页面运行时都需要添加这些控件。

    2. 您正在将控件呈现为字符串。不要那样做,只需将它们添加到页面控件树中,它们将在页面渲染期间自行渲染。

    3. 在创建控件时使用 Page.LoadControl()。这将创建控件并强制它的事件(页面事件生命周期)赶上页面的其余部分。

    4. 您在页面事件生命周期的后期添加控件。尝试在 Page_Init 中添加您的控件。

    这是一个将所有内容组合在一起的示例。它动态创建一个按钮,然后将其添加到占位符控件中。

    protected void Page_Init(object sender, System.EventArgs e)
    {
      var button = LoadControl(typeof(Button), null) as Button;
      button.Click += clickHandler;
      myPlaceholder.Controls.Add(button);
    }
    

    【讨论】:

    • 感谢您的详细解释,这一切都说得通。我只是不确定 2. 如何满足我的要求。正如我在问题中提到的,要显示的页面布局来自数据库,我需要将控件准确放置在内容中大括号的位置。所以我在构建一个字符串以显示为输出时加载控件,如果我不将渲染作为字符串进行,那么控件将如何准确放置在我想要的位置?
    • 您可以做 .net 所做的事情。将您的 HTML 放在 Literal 控件中并将其添加到控件树中。当您遇到按钮或文本字段时,为它们创建控件并将它们添加到控件树中。如果您在这些控件之后有更多 HTML,则将该 HTML 放在另一个 Literal 控件中并将其添加到控件树中。这不是一种有趣的构建页面的方式,但是如果您正在做一些有点疯狂的事情,例如基于从数据库中提取的字符串构建页面,那么您将经历一些痛苦的工作。
    • 嗯,这听起来很有挑战性。我遇到的问题是对.Net 中现有的经典 ASP 应用程序进行逆向工程。因此,HTML 来自数据库(在经典 ASP 中完成)的想法无法改变,因为我需要确保新应用程序与旧应用程序的工作方式完全相同,而无需进行任何更改。此外,模板的格式类似于“{header_stuff}{more_dynamic_stuff}static html and other things。所以大括号 {more_dynamic_stuff} 会有一堆控件。
    • 此外,动态添加的每个控件都需要在其前后具有 HTML,该 HTML 也来自数据库。如果有更简单的解决方案,您有什么建议吗?
    • 我不确定你是否抓住了它,但我在之前的评论中给了你如何处理 HTML 的答案。如果您想处理控件并触发它们的事件,那么您必须这样做。如果你真的只想使用字符串(而不是控件),那么你应该看看 WebForms 以外的东西。我认为 ASP.Net MVC 会更合适,而且听起来你对经典 ASP 比对 ASP.Net 更熟悉,所以 MVC 对你来说可能更容易过渡。
    【解决方案2】:

    控件必须在 Page_Init 中启动以将它们持久保存在视图状态中,如果视图状态中不存在控件,aspx 将无法理解注册了谁的事件。在 page_init 上初始化你的按钮

    【讨论】:

      【解决方案3】:

      使用PreInit 事件,如此处所述,http://msdn.microsoft.com/en-us/library/ms178472.aspx,这是您要添加动态控件的地方。实际上,您应该只需要执行 Page.Controls.Add() ,因为这发生在页面生命周期的早期,ASP 应该为您处理呈现。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-15
        • 2017-03-29
        相关资源
        最近更新 更多