Jon*_*ton 5 asp.net user-controls updatepanel webforms .net-4.5
在将项目从3.5迁移到4.5时,在ASP.Net WebForms中遇到了一个有趣的问题.
有问题的网站非常动态 - 该网页是基于CMS方式的配置构建的.
但是在4.5中我们遇到了一个问题 - 当通过按钮点击将更多内容添加到页面中时,并不会显示内容的所有标记.(测试时问题也在.net 4.0中重现).
这里演示的是一个非常简单的示例,它只使用默认的WebForms项目模板(在本例中为VB).
在Default.aspx中添加以下标记:
<asp:UpdatePanel ID="udpTrigger" runat="server" UpdateMode="Always">
<ContentTemplate>
<asp:button id="btnGo" runat="server" Text ="Go" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:Panel ID="pnlContainer" runat="server">
</asp:Panel>
Run Code Online (Sandbox Code Playgroud)
在Default.aspx.vb中添加以下代码:
Dim _udp As UpdatePanel
Private Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init
_udp = New UpdatePanel()
_udp.ID = "udpTarget"
_udp.UpdateMode = UpdatePanelUpdateMode.Conditional
pnlContainer.Controls.Add(_udp)
End Sub
Private Sub btnGo_Click(sender As Object, e As EventArgs) Handles btnGo.Click
Dim ctrl = LoadControl("Control.ascx")
Dim pnlWrapper = New Panel With {.ID = "pnlWrapper"}
pnlWrapper.Controls.Add(ctrl)
_udp.ContentTemplateContainer.Controls.Add(pnlWrapper)
_udp.Update()
End Sub
Run Code Online (Sandbox Code Playgroud)
注意:用户控件和更新面板之间有一个包装面板.这用于演示输出中缺少哪个标记.
创建Control.ascx并添加以下内容:
<asp:Panel ID="pnlControl" runat="server"></asp:Panel>
Run Code Online (Sandbox Code Playgroud)
单击btnGo控件后,应将包装器面板和control.ascx添加到页面中.
在.Net 3.5中正是如此:
<div id="pnlContainer">
<div id="udpTarget">
<div id="pnlWrapper">
<div id="ctl05_pnlControl">
</div>
</div>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
在.Net 4.5中,包装面板不会出现 - 只是用户控件:
<div id="MainContent_pnlContainer">
<div id="MainContent_udpTarget">
<div id="MainContent_ctl02_pnlControl">
</div>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
如果更新面板位于网页的标记中,则不会发生此问题,但在这种情况下,这是不可能的.
切换使用哪个LoadControl重载(LoadControl(type,params)生成包装器面板,但没有标记 - 这似乎有一个单独的问题).
在fiddler2中检查响应主体显示在服务器端省略了包装器面板(即我们在客户端ajax处理中没有丢失它)
那么有没有任何解决方法,甚至是针对这种行为的某种修补补丁 - 它看起来似乎是.Net 4的破损,因为它在3.5中很好.
现在也在我的博客上发布了这个,以收集我为修复或解决方法所做的任何尝试.
根据@ jadarnel27的指针,下面的步骤没有重现VS2010上的问题,我已经尝试了几台远离工作的机器上的步骤.
所以它看起来像这个问题仅限于VS2013.接下来在VS2013中尝试一些不同的设置.
现在已将此发布到Microsoft Connect此处.
我现在有一个解决办法。我使用UserControlLoader服务器控件来包装用户控件,并通过覆盖单独呈现它RenderContents
其代码为UserControlLoader:
''' <summary>
''' UserControl Loader - loads a user control
''' Works around a problem with ASP.Net Webforms in 4.0/4.5
''' </summary>
<ToolboxData("<{0}:UserControlLoader runat=server></{0}:UserControlLoader>")> _
Public Class UserControlLoader
Inherits WebControl
Public ReadOnly Property Control As Control
Get
Return _control
End Get
End Property
Private _control As Control
Public Sub LoadControl(page As Page, virtualPath As String)
_control = page.LoadControl(virtualPath)
Me.Controls.Add(_control)
End Sub
Public Overrides Sub RenderBeginTag(writer As HtmlTextWriter)
'Don't render anything
End Sub
Public Overrides Sub RenderEndTag(writer As HtmlTextWriter)
'Don't render anything
End Sub
''' <summary>
''' Overrides RenderContent to write the content to a separate writer,
''' then adds the rendered markup into the main HtmlTextWriter instance.
''' </summary>
Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)
If _control Is Nothing Then Return
Using sw = New StringWriter()
Using hw = New HtmlTextWriter(sw)
MyBase.RenderContents(hw)
writer.Write(sw.ToString)
End Using
End Using
End Sub
End Class
Run Code Online (Sandbox Code Playgroud)
用法:
为了将其实现到列出的重新创建步骤中,btnGo事件处理程序变为:
Private Sub btnGo_Click(sender As Object, e As EventArgs) Handles btnGo.Click
Dim loader = new UserControlLoader()
loader.LoadControl(Page,"Control.ascx")
Dim pnlWrapper = New Panel With {.ID = "pnlWrapper"}
pnlWrapper.Controls.Add(loader)
_udp.ContentTemplateContainer.Controls.Add(pnlWrapper)
_udp.Update()
End Sub
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
563 次 |
| 最近记录: |