持久化动态只读字段过去的初始化

Persisting Dynamic ReadOnly Field Past Initialisation

我在页面 load/init 上动态创建了一个只读文本框,并在第一次加载时(不是 IsPostBack)设置了文本。我在页面上还有一个按钮,它带有一个单击事件,可以更改文本框的内容。使用另一个按钮,我阅读了文本框的文本。问题如下:

  1. 如果我单击更改文本框的按钮,然后单击读取文本框文本的按钮,就没问题了。

  2. 如果我只是加载页面并单击读取文本框文本的按钮,它会返回一个空字符串

我需要这两种情况才能返回结果 - 无论是原始文本还是以编程方式更改的新文本。

示例代码:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Dim Textbox As New TextBox()
    Textbox.ID = "Bob"
    Textbox.ReadOnly = True
    If Not IsPostBack Then
        Textbox.Text = "Initial Text"
    End If
    Content.Controls.Add(Textbox)

    Dim Button As New Button()
    Button.Text = "Change text"
    AddHandler Button.Click, AddressOf Button_Click
    Content.Controls.Add(Button)
End Sub

Protected Sub Button_Click(ByVal sender As Object, ByVal e As EventArgs)
    'FindControlRecursive is locally defined - just finds a control based on root control and ID
    CType(FindControlRecursive(Content, "Bob"), TextBox).Text = "Hmmmmm"
End Sub

Private Sub Submit_Click(sender As Object, e As EventArgs) Handles Submit.Click
    Dim Textbox As TextBox = CType(FindControlRecursive(Content, "Bob"), TextBox)
    MsgBox(Textbox.Text)
End Sub

我可以每次都重新初始化文本框,但这只是一个例子,实际上我将从 SQL 中提取它,如果我在页面上有几个只读控件,我宁愿得到控件保留其文本而不是每次都返回 SQL。

我找到了两种解决方法,第二种是更受欢迎的方法(视情况而定):

  1. 专门将初始文本添加到视图状态,然后使用视图状态中的值在每个回传上设置文本:

    If Not IsPostBack Then
        Textbox.Text = "Initial Text"
        ViewState("Bob") = Textbox.Text
    Else
        Textbox.Text = ViewState("Bob")
    End If   
    
  2. 向文本框添加 PreRender 事件,将其文本设置为自身。这发生在 ViewState 开始被跟踪之后,因此它通过控件添加到视图状态并在回发中持久保存:

    If Not IsPostBack Then
        Textbox.Text = "Initial Text"
        AddHandler Textbox.PreRender, AddressOf PersistPastInitialLoad
    End If
    

    并添加新子:

    Protected Sub PersistPastInitialLoad(ByVal sender As Object, ByVal e As EventArgs)
        'This is just for example - would need refining for different types of controls
        CType(sender, TextBox).Text = CType(sender, TextBox).Text
    End Sub
    

本质上,它们都做同样的事情——将文本保存在视图状态中——但这取决于哪个是最好用的实现。第一个实现可能 read/work 更容易一些,但如果您单击按钮更改文本框文本,它会导致冗余视图状态膨胀(即,您将在视图状态中根据您创建的视图状态键获得初始文本以及由控件 onchange 添加到视图状态的当前文本。