为什么PreInit上的ClientID与Init或PreRender中的ClientID不同?

时间:2014-04-15 14:42:26

标签: asp.net vb.net

一点背景......在工作中我从Windows XP(32位)升级到Windows 7(64位)。在升级时,我也被改为:

  • Visual Web Developer 2005 Express Edition到Visual Studio Express 2013 for Web
  • ASP.Net 2.0至ASP.Net 4.5.1
  • Subversion to GitHub

我正在测试我的网站,以确保没有任何损坏,而且确实存在......通过我指定的密钥在ViewState中存储值似乎已经破坏了。

早期,我创建了一些用户控件(.ascx),让生活更轻松一些。为了保留属性,我将它们存储在ViewState中,它在ASP.Net 2.0中运行得非常好。

属性存储示例(来自我的ValidatedTextBox类,它是带有预定义验证程序的<asp:TextBox />

Private ReadOnly Property ViewStateControlPrefix() As String
    Get
        Return "Maggie:ValidatedTextBox:" & txt.ClientID & ":"
    End Get
End Property

Public Property TextMode() As System.Web.UI.WebControls.TextBoxMode
    Get
        If Not ViewState(Me.ViewStateControlPrefix & "TextMode") Is Nothing Then
            Return ViewState(Me.ViewStateControlPrefix & "TextMode")
        Else
            Return System.Web.UI.WebControls.TextBoxMode.SingleLine
        End If
    End Get
    Set(ByVal value As System.Web.UI.WebControls.TextBoxMode)
        ViewState(Me.ViewStateControlPrefix & "TextMode") = value
    End Set
End Property

现在已经发生了对ASP.Net 4.5.1的更新,这不再像我想象的那样有效。

ViewStateControlPrefix会返回我期望的内容(例如"Maggie:ValidatedTextBox:ctl00_cphMaggie_vtKeywords_txt:"),但这不是ViewState中的密钥实际上是什么(它应该是)。

以下是调试器中发生的事情的屏幕截图:

Weird Keys that I didn't set in ViewState

键的差异归结为ClientID属性。

Get中,它设置为ctl00_cphMaggie_vtResponse_txt,但Set设置为vtResponse_txt,这使我处于亏损状态我想要检索该值。

pages中的web.config元素自动添加了controlRenderingCompatibilityVersion="4.0"clientIDMode="AutoID",我怀疑clientIDMode与我的问题有关(尽管我尝试将其切换到Predictable但没有效果。我也尝试过使用UniqueID,但同样的问题发生了(分别为ctl00$cphMaggie$vtResponse$txtvtResponse$txt)。

我假设在Set上调用了PreInit,因为我通过ascx中的标记设置了属性:

<Maggie:ValidatedTextBox ID="vtResponse" runat="server" CSSClass="rte" TextMode="MultiLine" Columns="60" Rows="20" IsRequiredField="false" IsValidatedField="false" ScrubberFunction="trim(normalizeWhitespace(this));" ScrubberFunctionTrigger="onchange" />

Get明确调用PreRender

有人可以告诉我:

  • 为什么这在ASP.Net 2.0中有效,但现在不行?
  • 造成这种情况的原因是什么?
  • 我该如何解决?

更新

ClientIDMode切换为Static会使ClientID属性非常一致(尽管当多个ValidatedTextBox控件位于同一页面时不够独特)。

我还将此添加到控件的代码隐藏中:

Protected Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init
    Dim clientId As String = txt.ClientID
    Dim uniqueId As String = txt.UniqueID
    Dim h As Hashtable = New System.Collections.Hashtable(ViewState)
    Dim i As Integer = 0 'Used for a breakpoint
End Sub

暂停Dim i As Integer行之后,很明显,当Init事件触发时,ClientID属性已设置(并且以I&#的方式) 39; m曾经)。

此外,似乎没有{。1}}事件要在.ascx.vb代码隐藏中捕获(我得到PreInit),所以现在我真的很好奇当调用属性设置器时。

更新

我已经尝试了以下所有方法:

  1. "Event 'PreInit' cannot be found"更改为ViewStateControlPrefix
  2. Return "Maggie:ValidatedTextBox:" & txt.UniqueID & ":"添加到.ascx中的clientIDMode块。
  3. <%@ Control %>添加到.ascx中的clientIDMode
  4. <asp:Textbox />元素中循环显示AutoIDPredictableInheritStatic
  5. 循环浏览.ascx中pages块中的AutoIDPredictableInheritStatic
  6. 循环浏览.ascx中<%@ Control %>中的AutoIDPredictableInheritStatic
  7. <asp:Textbox />controlRenderingCompatibilityVersion更改为3.5更改为4.0
  8. 4.5
  9. 中的controlRenderingCompatibilityVersion元素中删除了clientIDModepages
  10. 狂热地(再次)搜索没有成功的解决方案。
  11. 用Google搜索确定何时在ASP.Net页面生命周期中设置web.config属性(也没有成功)。
  12. 我改变的事情似乎并不重要。当从getter调用时,ClientID getter返回ViewStateControlPrefix,并且当从getter调用时,其他内容(取决于我已经更改的内容)。

    有没有人知道为什么这种行为与ASP.Net 2.0有如此根本的不同?或者如何改回来?

1 个答案:

答案 0 :(得分:0)

我提出的解决方法是重新编写ViewStateControlPrefix getter以返回独立于ClientIDMode设置的唯一值:

Private ReadOnly Property ViewStateControlPrefix() As String
    Get
        Dim parts As String() = Me.ClientID.Split("_")
        Dim id As String = Me.ClientID 'Default to ClientID
        Dim prefix As String = String.Empty

        If parts.Length > 0 Then
            'By using Me.ClientID, the last element of the array will always be
            'the ID specified in the markup, regardless of ClientIDMode settings.
            id = parts(parts.GetUpperBound(0))
        End If

        prefix = "Maggie:ValidatedTextBox:" & id & ":"

        Return prefix
    End Get
End Property

这将返回一个一致的值,以用作ViewState包中的键,无论何时调用此getter并且无论ClientIDMode设置如何(无论何时设置它们)。

我会暂时不接受这个答案

  • 任何人都可以提出更好的解决方案
  • 或任何人都可以在帖子中解释我的任何原始问题:
    • 为什么这在ASP.Net 2.0中有效,但现在不行?
    • 造成这种情况的原因是什么?
    • 我该如何解决?
    • 在Page LifeCycle中,当以声明方式设置属性时,会调用属性设置器吗?
    • 为什么这种行为与ASP.Net 2.0完全不同?
    • 如何改回来?