asp.net - 为什么PreInit上的ClientID与Init或PreRender中的ClientID不同?

标签 asp.net vb.net

有点背景...在工作中,我已从Windows XP(32位)升级到Windows 7(64位)。升级时,我也从以下位置切换:


Visual Web Developer 2005速成版到Web的Visual Studio Express 2013
从ASP.Net 2.0到ASP.Net 4.5.1
转换到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中的键实际是(应该是)。

这是调试器中发生的情况的屏幕截图:



键的区别归结为ClientID属性。

Get中,将其设置为ctl00_cphMaggie_vtResponse_txt,但在Set中,将其设置为vtResponse_txt,这使我在要检索值时不知所措。

pages中的web.config元素已自动添加了controlRenderingCompatibilityVersion="4.0"clientIDMode="AutoID",我怀疑与我的问题有关(尽管我尝试将其切换为clientIDMode无效) )。我也尝试使用Predictable,但是会出现相同的问题(分别从UniqueIDctl00$cphMaggie$vtResponse$txt)。

我假设在vtResponse$txt上调用了Set,因为我是通过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" />


并且PreInitGet上显式调用。

有人可以启发我:


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


更新

PreRender切换为ClientIDMode可使Static属性非常一致(尽管在同一页面上有多个ClientID控件时,其唯一性不足)。

我还将此添加到控件的代码后面:

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


暂停ValidatedTextBox行之后,很明显,在触发Dim i As Integer事件时,已设置Init属性(并且使用我惯用的方式)。

另外,在.ascx.vb代码后面(我得到ClientID)中似乎没有要捕获的PreInit事件,所以现在我真的很好奇何时调用属性设置器。

更新

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


"Event 'PreInit' cannot be found"更改为ViewStateControlPrefix
在.ascx中的Return "Maggie:ValidatedTextBox:" & txt.UniqueID & ":"块中添加了clientIDMode
在.ascx中的<%@ Control %>中添加了clientIDMode
<asp:Textbox />元素中的AutoIDPredictableInheritStatic中循环。
在.ascx的pages块中的AutoIDPredictableInheritStatic中循环。
在.ascx中的<%@ Control %>中的AutoIDPredictableInheritStatic中循环。
<asp:Textbox />controlRenderingCompatibilityVersion更改为3.54.0
4.5controlRenderingCompatibilityVersion元素中删除了clientIDModepages
Google再次狂热地寻求解决方案,但没有成功。
使用Googled来确定在ASP.Net页面生命周期中何时设置了web.config属性(也没有成功)。


我更改什么似乎并不重要。从设置器调用时,ClientID吸气剂将返回ViewStateControlPrefix,从getter调用时,其他内容(取决于我所做的更改)将返回。

有谁知道为什么这种行为与ASP.Net 2.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中有效,但现在不行?
是什么原因造成的?
我该如何解决?
在页面生命周期中何时以声明方式设置属性时调用属性设置器?
为什么这种行为与ASP.Net 2.0如此根本不同?
如何改回来?

关于asp.net - 为什么PreInit上的ClientID与Init或PreRender中的ClientID不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23087047/

相关文章:

c# - 使用电子表格工具打开 protected 工作簿

vb.net - 如何在 VB.net 中将 24 小时制转换为 12 小时制为 hh :mm AM/PM

c# - 按字母顺序和类型对列表进行排序

c# - 我的项目使用什么语言?

vb.net - 保持来自 redis 服务器的响应对每个连接的客户端都是唯一的

c# - 从 GridView 复选框更新数据库

c# - 单击按钮时使用 JS 更改 asp :HiddenField. 值

c# - 使用 C# WebClient 并获取异常时,如何在响应中显示可选字段?

javascript - 为什么 ValidatorValidate() 验证页面上的所有 RequiredFieldValidator 控件?

vb.net - 如何获取可以访问其属性的文本框列表