GridView排序后如何正确选中行并绑定至Repeater控件
问题分析与解决方法
问题根源
你当前的排序逻辑只修改了DataTable.DefaultView的排序规则,但原DataTable的行顺序完全没变化。GridView显示的是排序后的DataView,但复制行时你用gRow.RowIndex去读取原DataTable的行,自然取到的是排序前的旧数据。
两种可行修复方案
方案一:将排序后的DataView转为新DataTable保存
修改排序代码,把排序后的DataView转换成新的DataTable,替换ViewState里保存的原数据,这样GridView和ViewState里的DataTable行顺序完全一致:
protected void GridView1_Sorting1(object sender, GridViewSortEventArgs e) { DataTable dtrslt = (DataTable)ViewState["dirState"]; if (dtrslt.Rows.Count > 0) { string sortDirection = Convert.ToString(ViewState["sortdr"]) == "Asc" ? "Desc" : "Asc"; // 排序后将DataView转为新DataTable DataView sortedView = new DataView(dtrslt); sortedView.Sort = $"{e.SortExpression} {sortDirection}"; DataTable sortedTable = sortedView.ToTable(); ViewState["sortdr"] = sortDirection; ViewState["sortexp"] = e.SortExpression; // 保存排序后的DataTable到ViewState ViewState["dirState"] = sortedTable; GridView1.DataSource = sortedTable; GridView1.DataBind(); } }
方案二:直接从GridView行的DataItem获取当前显示数据
如果不想修改排序逻辑,复制行时直接读取GridView行绑定的DataRowView,而不是通过索引去原DataTable取:
protected void CopyToDataTable(object sender, EventArgs e) { DataTable dtNotary = new DataTable(); DataTable dtrslt = (DataTable)ViewState["dirState"]; dtNotary = dtrslt.Clone(); foreach (GridViewRow gRow in GridView1.Rows) { CheckBox ckBox = (CheckBox)gRow.FindControl("notaryselect"); if (ckBox.Checked && gRow.DataItem != null) { // 从当前行的DataItem获取排序后的DataRowView DataRowView rowView = (DataRowView)gRow.DataItem; dtNotary.ImportRow(rowView.Row); } } RepeaterNotary.DataSource = dtNotary; RepeaterNotary.DataBind(); }
额外建议
- 优先用方案一,这样ViewState里保存的就是和界面一致的数据,后续其他操作也不会出现索引不匹配的问题。
- 如果数据量较大,要注意ViewState的大小,避免影响页面性能,此时可以考虑用Session替代,或者每次排序重新从数据源获取数据。
内容的提问来源于stack exchange,提问作者ACME NOTARY
相关产品推荐
相关产品推荐

