5级分组下打印单级GroupHeader遇控制台错误求助
解决Radzen WinForms分组表头打印的空引用错误
问题背景
我需要在Windows Forms应用中实现5级分组的GroupHeader打印样式,原打印效果不符合预期。修改模板代码后实现了预期样式,但控制台出现空引用错误。
原代码实现
原GroupHeaderTemplate代码
<GroupHeaderTemplate> @if (context.GroupDescriptor.Property == "NomCuenta1" || context.GroupDescriptor.Property == "NomCuenta2") { <b style="font-weight:bold">@(context.Data.Key ?? "")</b> } else { @(context.Data.Key ?? "") } @{ var props = typeof(GetBalancePrueba_Result).GetProperties() .Where(p => selectedColumns.Contains(p.Name) && (p.PropertyType == typeof(decimal?) || p.PropertyType == typeof(decimal)) ); foreach (var prop in props) { var sum = ((IEnumerable<GetBalancePrueba_Result>)context.Data.Items) .Select(x => prop.GetValue(x)) .Where(v => v != null) .Select(v => Convert.ToDecimal(v)) .Sum(); <text> | @prop.Name: @sum.ToString("N3")</text> } } </GroupHeaderTemplate>
分组配置代码
// Construir la agrupación dinámica basada en los niveles realmente presentes var grupos = new System.Collections.ObjectModel.ObservableCollection<Radzen.GroupDescriptor>(); grupos.Add(new Radzen.GroupDescriptor() { Property = "NomCuenta1", SortOrder = SortOrder.Ascending, FormatString = "{0}" }); grupos.Add(new Radzen.GroupDescriptor() { Property = "NomCuenta2", SortOrder = SortOrder.Ascending, FormatString = "{0}" }); grupos.Add(new Radzen.GroupDescriptor() { Property = "NomCuenta3", SortOrder = SortOrder.Ascending, FormatString = "{0}" }); grupos.Add(new Radzen.GroupDescriptor() { Property = "NomCuenta4", SortOrder = SortOrder.Ascending, FormatString = "{0}" }); grupos.Add(new Radzen.GroupDescriptor() { Property = "NomCuenta5", SortOrder = SortOrder.Ascending, FormatString = "{0}" }); // Asignar la nueva estructura de agrupación if (grdMain != null) { grdMain.Groups = grupos; StateHasChanged(); }
修改后出现空引用的代码
<GroupHeaderTemplate> @if(!ReportFilterModel.DetallarValue){ var nomCuenta = context.Data.GetType().GetProperty("NomCuenta1")?.GetValue(context.Data)?.ToString() ?? context.Data.GetType().GetProperty("NomCuenta2")?.GetValue(context.Data)?.ToString() ?? context.Data.GetType().GetProperty("NomCuenta3")?.GetValue(context.Data)?.ToString() ?? context.Data.GetType().GetProperty("NomCuenta4")?.GetValue(context.Data)?.ToString() ?? context.Data.GetType().GetProperty("NomCuenta5")?.GetValue(context.Data)?.ToString(); nomCuenta = nomCuenta ?? ""; var cuentaPart = nomCuenta.Split('-').FirstOrDefault(); var nivCta = cuentaPart != null ? cuentaPart.Length == 1 ? 1 : cuentaPart.Length == 2 ? 2 : 0 : 0; <b style="font-weight:bold">@context.Data.Key?.ToString() ?? ""</b> var props = typeof(GetBalancePrueba_Result).GetProperties() .Where(p => selectedColumns.Contains(p.Name) && (p.PropertyType == typeof(decimal?) || p.PropertyType == typeof(decimal)) ); foreach (var prop in props) { var sum = ((IEnumerable<GetBalancePrueba_Result>)context.Data.Items) .Select(x => prop.GetValue(x)) .Where(v => v != null) .Select(v => Convert.ToDecimal(v)) .Sum(); <text> | @prop.Name: @sum.ToString("N3")</text> } } else { @if (context.GroupDescriptor.Property == "NomCuenta1" || context.GroupDescriptor.Property == "NomCuenta2") { <b style="font-weight:bold">@(context.Data.Key ?? "")</b> } else { @(context.Data.Key ?? "") } var props = typeof(GetBalancePrueba_Result).GetProperties() .Where(p => selectedColumns.Contains(p.Name) && (p.PropertyType == typeof(decimal?) || p.PropertyType == typeof(decimal)) ); foreach (var prop in props) { var sum = ((IEnumerable<GetBalancePrueba_Result>)context.Data.Items) .Select(x => prop.GetValue(x)) .Where(v => v != null) .Select(v => Convert.ToDecimal(v)) .Sum(); <text> | @prop.Name: @sum.ToString("N3")</text> } } </GroupHeaderTemplate>
错误原因分析
- 反射逻辑错误:
context.Data是分组容器对象,并非GetBalancePrueba_Result实体,直接通过GetType().GetProperty("NomCuentaX")无法获取目标属性,会返回null触发空引用。 - Razor语法错误:
@context.Data.Key?.ToString() ?? ""未用括号包裹,Razor解析时会出现表达式识别异常。 - 缺少空值校验:未对
selectedColumns、context.Data.Items做非空判断,当这些对象为空时直接操作会触发空引用。
修正后的代码
<GroupHeaderTemplate> @if(!ReportFilterModel.DetallarValue){ // 直接通过当前分组的Descriptor获取分组值,无需反射遍历 var nomCuenta = context.Data.Key?.ToString() ?? ""; var cuentaPart = nomCuenta.Split('-').FirstOrDefault(); var nivCta = cuentaPart != null ? cuentaPart.Length == 1 ? 1 : cuentaPart.Length == 2 ? 2 : 0 : 0; // 修复Razor表达式语法,用括号包裹完整逻辑 <b style="font-weight:bold">@(context.Data.Key?.ToString() ?? "")</b> // 先校验selectedColumns是否为空 if(selectedColumns != null){ var props = typeof(GetBalancePrueba_Result).GetProperties() .Where(p => selectedColumns.Contains(p.Name) && (p.PropertyType == typeof(decimal?) || p.PropertyType == typeof(decimal))); foreach (var prop in props) { // 校验分组Items是否为空,再安全转换类型 var items = context.Data.Items as IEnumerable<GetBalancePrueba_Result>; if(items != null){ var sum = items.Select(x => prop.GetValue(x)) .Where(v => v != null) .Select(v => Convert.ToDecimal(v)) .Sum(); <text> | @prop.Name: @sum.ToString("N3")</text> } } } } else { @if (context.GroupDescriptor.Property == "NomCuenta1" || context.GroupDescriptor.Property == "NomCuenta2") { <b style="font-weight:bold">@(context.Data.Key ?? "")</b> } else { @(context.Data.Key ?? "") } if(selectedColumns != null){ var props = typeof(GetBalancePrueba_Result).GetProperties() .Where(p => selectedColumns.Contains(p.Name) && (p.PropertyType == typeof(decimal?) || p.PropertyType == typeof(decimal))); foreach (var prop in props) { var items = context.Data.Items as IEnumerable<GetBalancePrueba_Result>; if(items != null){ var sum = items.Select(x => prop.GetValue(x)) .Where(v => v != null) .Select(v => Convert.ToDecimal(v)) .Sum(); <text> | @prop.Name: @sum.ToString("N3")</text> } } } } </GroupHeaderTemplate>
关键修改说明
- 简化分组值获取:直接使用
context.Data.Key获取当前分组的显示值,替代错误的反射逻辑。 - 修复Razor语法:将未包裹的表达式用
@()包裹,确保Razor正确解析。 - 增加空值校验:对
selectedColumns、context.Data.Items添加非空判断,避免空引用异常。 - 安全类型转换:用
as关键字转换context.Data.Items类型,避免强制转换失败。
内容的提问来源于stack exchange,提问作者Juan Sebastian Rodriguez
相关产品推荐
相关产品推荐

