如何在DevExpress GridView分页时保存DataItemTemplate中ASPxTextBox的值
解决ASPxGridView分页时保留DataItemTemplate中文本框输入值的问题
这个问题我之前帮不少开发者解决过,本质是当你切换GridView页码触发回发/回调时,GridView会重新渲染当前页的行,DataItemTemplate里的ASPxTextBox属于动态生成的控件,默认情况下这些输入值不会自动被保留,所以返回原页面就丢了。下面给你几个实用的解决方案:
方法一:服务器端用ViewState手动保存输入值
这是最经典的服务器端方案,通过捕获文本框的输入事件,把值存到ViewState里,渲染行时再取出来赋值:
- 先给ASPxTextBox配置
TextChanged事件和必要属性:
<dx:GridViewDataColumn FieldName="YourColumnName"> <DataItemTemplate> <dx:ASPxTextBox ID="txtInput" runat="server" AutoPostBack="True" EnableViewState="True" OnTextChanged="txtInput_TextChanged"> </dx:ASPxTextBox> </DataItemTemplate> </dx:GridViewDataColumn>
- 在后台实现
TextChanged事件,把输入值绑定到行主键保存到ViewState:
protected void txtInput_TextChanged(object sender, EventArgs e) { var txtBox = sender as ASPxTextBox; var container = txtBox.NamingContainer as GridViewDataItemTemplateContainer; // 用行的主键作为唯一标识,确保不同行的文本框值不会冲突 string rowKey = container.KeyValue.ToString(); // 初始化存储字典 if (ViewState["TextBoxValues"] == null) ViewState["TextBoxValues"] = new Dictionary<string, string>(); var valueDict = (Dictionary<string, string>)ViewState["TextBoxValues"]; valueDict[rowKey] = txtBox.Text; }
- 最后在GridView的
HtmlDataCellPrepared事件中,渲染行时从ViewState取值填充文本框:
protected void grid_HtmlDataCellPrepared(object sender, ASPxGridViewTableDataCellEventArgs e) { // 匹配你的目标列 if (e.DataColumn.FieldName != "YourColumnName") return; var txtBox = e.Cell.FindControl("txtInput") as ASPxTextBox; if (txtBox == null || ViewState["TextBoxValues"] == null) return; string rowKey = e.KeyValue.ToString(); var valueDict = (Dictionary<string, string>)ViewState["TextBoxValues"]; if (valueDict.ContainsKey(rowKey)) txtBox.Text = valueDict[rowKey]; }
方法二:客户端用本地存储(LocalStorage)保存值
如果不想频繁触发服务器回发,用客户端脚本把值存在浏览器本地,分页后再恢复,体验更流畅:
- 给GridView和文本框配置客户端事件:
<dx:ASPxGridView ID="grid" runat="server" ClientInstanceName="grid" EnableCallbacks="True"> <ClientSideEvents EndCallback="onGridEndCallback" /> <Columns> <dx:GridViewDataColumn FieldName="YourColumnName"> <DataItemTemplate> <dx:ASPxTextBox ID="txtInput" runat="server" ClientInstanceName="txtInput"> <ClientSideEvents TextChanged="onTextBoxInput" /> </dx:ASPxTextBox> </DataItemTemplate> </dx:GridViewDataColumn> </Columns> </dx:ASPxGridView>
- 编写客户端脚本实现保存和恢复逻辑:
// 文本框内容变化时,把值存在LocalStorage,用行主键作为唯一标识 function onTextBoxInput(s, e) { var rowIndex = s.GetParent().GetParent().index; var rowKey = grid.GetRowKey(rowIndex); localStorage.setItem(`grid_${grid.name}_textbox_${rowKey}`, s.GetText()); } // GridView分页回调完成后,恢复当前页所有文本框的值 function onGridEndCallback(s, e) { var visibleRows = s.GetVisibleRowsOnPage(); for(let i = 0; i < visibleRows; i++){ var rowKey = s.GetRowKey(i); var savedValue = localStorage.getItem(`grid_${grid.name}_textbox_${rowKey}`); if(savedValue){ var txtBox = s.FindRowCellTemplateControl(i, "YourColumnName", "txtInput"); if(txtBox) txtBox.SetText(savedValue); } } }
如果只想在当前会话保存,把localStorage换成sessionStorage即可。
方法三:回调时传递值到服务器保存
如果你的GridView用的是回调模式分页(EnableCallbacks="True"),可以在分页前收集所有输入值,通过CustomCallback传递到服务器存起来,分页后再恢复:
- 配置GridView的客户端BeginCallback事件:
<dx:ASPxGridView ID="grid" runat="server" ClientInstanceName="grid" EnableCallbacks="True" OnCustomCallback="grid_CustomCallback"> <ClientSideEvents BeginCallback="onGridBeginCallback" /> <!-- 列配置略 --> </dx:ASPxGridView>
- 客户端脚本收集值并传递:
function onGridBeginCallback(s, e) { var inputValues = {}; var visibleRows = s.GetVisibleRowsOnPage(); for(let i = 0; i < visibleRows; i++){ var rowKey = s.GetRowKey(i); var txtBox = s.FindRowCellTemplateControl(i, "YourColumnName", "txtInput"); if(txtBox) inputValues[rowKey] = txtBox.GetText(); } // 把值序列化为JSON作为参数传递 e.customArgs["InputValues"] = JSON.stringify(inputValues); }
- 服务器端CustomCallback事件中保存值:
protected void grid_CustomCallback(object sender, ASPxGridViewCustomCallbackEventArgs e) { if (!string.IsNullOrEmpty(e.Parameters) && e.CustomArgs.ContainsKey("InputValues")) { string json = e.CustomArgs["InputValues"].ToString(); var valueDict = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(json); ViewState["TextBoxValues"] = valueDict; } }
之后同样在HtmlDataCellPrepared事件中恢复值,和方法一的第三步一致。
注意事项
- 确保你的GridView有设置主键列(
KeyFieldName),这样才能获取到唯一的行标识; - 如果用服务器端方案,要保证GridView的
EnableViewState="True"(默认是开启的); - 大数据量场景下,ViewState可能会变大,此时客户端方案会更合适。
内容的提问来源于stack exchange,提问作者Morteza Jangjoo
相关产品推荐
相关产品推荐

