ASP WebForms中DataBinder.Eval处理含点列名取值失败求助
解决DataBinder.Eval处理带点字段名的问题
你碰到的这个问题我之前也遇到过——DataBinder.Eval会把字段名里的点(.)当成对象属性层级的分隔符,比如它会把"EN.DESARROLLO"解析成先取EN属性,再获取该属性下的DESARROLLO属性,而不是把整个字符串当作一个完整的字段名。下面给你几个实用的解决办法,结合你的代码来调整:
方法1:直接用DataRowView访问(最简便高效)
如果你的GridView绑定的是DataTable或DataSet,那么e.Row.DataItem本质是DataRowView类型,你可以直接通过索引器访问带点的字段名,完全绕过DataBinder.Eval的解析逻辑。
修改你代码里的问题行:
// 替换原来的DataBinder.Eval调用 DataRowView rowView = (DataRowView)e.Row.DataItem; int n = Convert.ToInt32(rowView[estados[i].Descripcion]);
这个方法最直接,不需要额外的工具方法,适合大部分WebForms绑定DataTable的场景。
方法2:用反射手动取值(通用兼容场景)
如果你的数据源不是DataRowView,而是自定义业务对象,那可以用反射来直接获取字段/属性值,跳过DataBinder.Eval的规则限制:
// 先写一个通用的取值工具方法 private object GetFieldValue(object dataItem, string fieldName) { // 优先处理DataRowView场景 if (dataItem is DataRowView rowView) { return rowView[fieldName]; } // 自定义对象用反射取属性 var prop = dataItem.GetType().GetProperty(fieldName); if (prop != null) { return prop.GetValue(dataItem); } // 也可以兼容字段(如果数据源是字段而非属性) var field = dataItem.GetType().GetField(fieldName); if (field != null) { return field.GetValue(dataItem); } return null; } // 然后在你的RowDataBound事件里调用: int n = Convert.ToInt32(GetFieldValue(e.Row.DataItem, estados[i].Descripcion));
这个方法兼容性更强,不管数据源是DataRowView还是自定义对象都能处理。
方法3:提前修改数据源的字段名(预防式方案)
如果你能控制数据源的生成逻辑,还可以在绑定GridView之前,把带点的字段名替换成其他字符(比如下划线_),从根源上避免问题:
// 假设你的数据源是DataTable DataTable dt = GetYourDataSource(); foreach (DataColumn col in dt.Columns) { if (col.ColumnName.Contains(".")) { col.ColumnName = col.ColumnName.Replace(".", "_"); } } // 同步修改estados里的描述值(因为字段名变了) foreach (var estado in estados) { if (estado.Descripcion.Contains(".")) { estado.Descripcion = estado.Descripcion.Replace(".", "_"); } } grdTecnicos.DataSource = dt; grdTecnicos.DataBind();
这样后续用DataBinder.Eval就不会有解析问题了,适合需要长期维护的场景。
结合你的代码修改后的完整示例
推荐优先用方法1,修改后的代码片段如下:
private int[] totales = new int[100]; protected void grdTecnicos_RowDataBound(object sender, GridViewRowEventArgs e) { List<diccListaString> estados = getEstadosAbiertos(); try { if (e.Row.RowType == DataControlRowType.DataRow) { // 转换为DataRowView DataRowView rowView = (DataRowView)e.Row.DataItem; for (int i = 0; i < estados.Count() + 2; i++) { BoundField field = (BoundField)((DataControlFieldCell)e.Row.Cells[i]).ContainingField; if (field.HeaderText == "TOTAL") { int ac = totales[i - 1]; // 这里也可以改用rowView访问,保持统一 int n = Convert.ToInt32(rowView["TOTAL"]); totales[i - 1] = ac + n; } else if (i < estados.Count()) { int ac = totales[i]; // 直接用rowView访问带点的字段名 int n = Convert.ToInt32(rowView[estados[i].Descripcion]); totales[i] = ac + n; } } } else if (e.Row.RowType == DataControlRowType.Footer) { for (int i = 0; i <= estados.Count() + 1; i++) { if (i == 0) e.Row.Cells[0].Text = "TOTAL:"; else e.Row.Cells[i].Text = totales[i - 1].ToString(); } } } catch (Exception err) { mostrar_error(err); } }
这样应该就能解决你遇到的带点字段名取值失败的问题了。
内容的提问来源于stack exchange,提问作者Dave Salazar
相关产品推荐
相关产品推荐

