ASP.NET页面回发时使用ViewState保存字符串数组的问题
解决ASP.NET中ViewState持久化字符串数组的问题
你在ViewState的使用逻辑上走偏啦——现在每次点击提交按钮都把单个字符串覆盖到ViewState("jobs")里,而且页面级的jobs数组在每次回发时都会被重新初始化,自然存不住之前的数据。咱们一步步来修正这个问题:
问题根源分析
- 页面级变量
jobs()和i在每次页面回发(比如点击按钮)时都会被重新创建,之前的值会直接丢失,没法依赖它们保存状态。 - 当前
btnAddToBatch_Click的逻辑是把单个输入文本直接赋值给ViewState("jobs"),相当于每次都覆盖掉之前的数据,根本没实现“累加”到数组的效果。 Page_Load里的赋值逻辑完全错误,你试图把单个字符串赋值给数组的某个索引,但此时jobs是刚初始化的空数组,必然会出问题。
修正后的代码实现
我们需要把整个字符串数组存在ViewState中,每次添加新元素时,先取出已有数组、追加新元素,再存回ViewState:
' 不需要页面级的jobs数组和i变量,改用ViewState维护状态 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load ' 首次加载时初始化ViewState,创建空的字符串数组 If Not IsPostBack Then ViewState("jobs") = New String() {} End If End Sub Protected Sub btnAddToBatch_Click(sender As Object, e As EventArgs) Handles btnAddToBatch.Click If Not String.IsNullOrEmpty(txtJob.Text) Then ' 1. 从ViewState取出已有的字符串数组 Dim currentJobs As String() = DirectCast(ViewState("jobs"), String()) ' 2. 创建新数组,长度比原数组多1,容纳新元素 Dim newJobs As String() = New String(currentJobs.Length) {} ' 3. 复制原数组元素到新数组 Array.Copy(currentJobs, newJobs, currentJobs.Length) ' 4. 把新输入的字符串加入新数组末尾 newJobs(currentJobs.Length) = txtJob.Text.Trim() ' 5. 将更新后的数组存回ViewState ViewState("jobs") = newJobs ' 6. 清空文本框,方便继续输入 txtJob.Text = String.Empty End If End Sub ' 新增:读取数组并执行业务逻辑的按钮事件 Protected Sub btnProcessBatch_Click(sender As Object, e As EventArgs) Handles btnProcessBatch.Click ' 从ViewState取出完整数组 Dim allJobs As String() = DirectCast(ViewState("jobs"), String()) ' 执行你的业务逻辑,比如遍历处理每个元素 For Each job As String In allJobs ' 这里替换成你的业务代码,比如写入数据库或页面输出 Response.Write($"处理任务:{job}<br/>") Next End Sub
关键要点说明
- ViewState存储整个数组:ViewState可以序列化存储.NET对象(字符串数组默认支持序列化),所以直接把整个数组存进去,而非单个值。
- 抛弃页面级变量依赖:页面每次回发都会重新实例化,页面级变量无法跨回发保存状态,必须用ViewState、Session等持久化容器。
- 更简洁的List版本:因为.NET数组是固定长度的,手动扩容有点麻烦,你也可以改用
List(Of String)(同样支持序列化存到ViewState),代码会更简洁:
改用List(Of String)的简化实现
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load If Not IsPostBack Then ViewState("jobsList") = New List(Of String)() End If End Sub Protected Sub btnAddToBatch_Click(sender As Object, e As EventArgs) Handles btnAddToBatch.Click If Not String.IsNullOrEmpty(txtJob.Text) Then Dim jobsList As List(Of String) = DirectCast(ViewState("jobsList"), List(Of String)) jobsList.Add(txtJob.Text.Trim()) ViewState("jobsList") = jobsList txtJob.Text = String.Empty End If End Sub Protected Sub btnProcessBatch_Click(sender As Object, e As EventArgs) Handles btnProcessBatch.Click Dim jobsList As List(Of String) = DirectCast(ViewState("jobsList"), List(Of String)) For Each job As String In jobsList ' 业务逻辑处理 Response.Write($"处理任务:{job}<br/>") Next End Sub
这个版本不需要手动处理数组扩容,用起来更顺手,推荐你试试。
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

