使用ItemTemplate时GridView排序功能失效问题求助
问题分析与解决方案
我仔细看了你的代码,发现排序功能不生效的核心原因就在你的gvwSacBus_Docs_Sorting方法里——你在最后两行又重新绑定了未排序的原始List,直接把之前准备好的排序后的DataView覆盖了!
// 这里你已经把数据源设为排序后的sortedView了 gvwSacBus_Docs.DataSource = sortedView; // 但紧接着又重新绑定了原始的未排序List,等于白做了排序! gvwSacBus_Docs.DataSource = cajaBL.sacbus_Consul_Cajas_x_Cont(lbl_SacBus_CliCod.Text, txt_SacBus_Criter.Text); gvwSacBus_Docs.DataBind();
下面是完整的修正和优化方案:
1. 修正排序事件逻辑
首先去掉覆盖数据源的错误代码,同时优化查询逻辑(避免每次排序都重复调用数据库,提升性能):
protected void gvwSacBus_Docs_Sorting(object sender, GridViewSortEventArgs e) { // 先从缓存获取数据(避免重复查库),如果没有再查询 List<Cajas> cajaList; if (ViewState["CachedCajaList"] == null) { cajaList = cajaBL.sacbus_Consul_Cajas_x_Cont(lbl_SacBus_CliCod.Text, txt_SacBus_Criter.Text); ViewState["CachedCajaList"] = cajaList; } else { cajaList = (List<Cajas>)ViewState["CachedCajaList"]; } // 转换为DataTable ListtoDataTable lsttodt = new ListtoDataTable(); DataTable databito = lsttodt.ToDataTable(cajaList); // 处理排序方向(用当前排序字段作为ViewState键,支持多字段排序) string sortExpression = e.SortExpression; SortDirection currentDir; if (ViewState["SortDirection_" + sortExpression] == null) { currentDir = SortDirection.Ascending; } else { currentDir = (SortDirection)ViewState["SortDirection_" + sortExpression]; // 切换排序方向 currentDir = currentDir == SortDirection.Ascending ? SortDirection.Descending : SortDirection.Ascending; } ViewState["SortDirection_" + sortExpression] = currentDir; string sortDir = currentDir == SortDirection.Ascending ? "Asc" : "Desc"; // 应用排序 DataView sortedView = new DataView(databito); sortedView.Sort = $"{sortExpression} {sortDir}"; // 缓存排序后的视图,方便分页使用 ViewState["SortedCajaView"] = sortedView; // 绑定排序后的数据源 gvwSacBus_Docs.DataSource = sortedView; gvwSacBus_Docs.DataBind(); }
2. 适配分页功能
因为你提到应用启用了分页,需要确保分页是基于排序后的数据源。如果使用GridView自带的分页,需要在PageIndexChanging事件里重新绑定排序后的数据源:
protected void gvwSacBus_Docs_PageIndexChanging(object sender, GridViewPageEventArgs e) { gvwSacBus_Docs.PageIndex = e.NewPageIndex; // 优先使用缓存的排序后视图,没有则用原始缓存数据 if (ViewState["SortedCajaView"] != null) { gvwSacBus_Docs.DataSource = (DataView)ViewState["SortedCajaView"]; } else if (ViewState["CachedCajaList"] != null) { gvwSacBus_Docs.DataSource = ViewState["CachedCajaList"]; } gvwSacBus_Docs.DataBind(); }
3. 其他优化建议
- 优化List转DataTable工具类:当前代码没有处理值类型的Nullable属性(如果以后实体类有
int?这类字段会报错),可以修改一下:
public class ListtoDataTable { public DataTable ToDataTable<T>(List<T> items) { DataTable dataTable = new DataTable(typeof(T).Name); PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo prop in Props) { // 获取属性的真实类型(处理Nullable) Type colType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType; dataTable.Columns.Add(prop.Name, colType); } foreach (T item in items) { object[] values = new object[Props.Length]; for (int i = 0; i < Props.Length; i++) { // 获取值,处理Nullable的null情况 values[i] = Props[i].GetValue(item) ?? DBNull.Value; } dataTable.Rows.Add(values); } return dataTable; } }
- 避免空异常:在数据层的
Cajas_Buscar_CajaXCont方法里,dr["F.EMI"]的处理可以更严谨,比如先判断列的索引再检查是否为DBNull:
int fecEmiIndex = dr.GetOrdinal("F.EMI"); if (dr.IsDBNull(fecEmiIndex)) { cajaBus.FecEmisionDoc = new DateTime(9999, 1, 1); } else { cajaBus.FecEmisionDoc = dr.GetDateTime(fecEmiIndex); }
这样修改后,你的GridView排序功能应该就能正常工作了,同时分页也能适配排序后的结果。
内容的提问来源于stack exchange,提问作者angel_neo
相关产品推荐
相关产品推荐

