MVC中ViewBag布尔值判断失效,始终显示列如何修复?
问题根源分析
你遇到的问题核心在于 ViewBag是全局共享的对象:在控制器的foreach循环中,每一次迭代都会覆盖ViewBag.showColumns的值,最终只有最后一个Site的判断结果会被保留下来。视图里所有Site都共用这同一个全局的showColumns值,自然会出现不管个别osiTotal是否为0,表格列都统一显示/隐藏的问题。
修复方案
这里提供两种常用的解决思路,你可以根据自己的代码结构选择:
方案一:给Site类添加专属状态属性
最直观的方式是给Site实体新增一个布尔属性,把每个站点的显示状态直接绑定到对象本身:
控制器代码修改
foreach (Site s in sites) { var OffReportRows = new Queue<List<string>>(); // 给当前Site标记是否需要显示列 s.ShowColumns = osiTotal[s.ID] > 0; if (s.ShowColumns) { OffReportRows.Enqueue(new List<string> { "Parts", "", "", osiPartCost[s.ID].ToString("C2"), "", "", osiPartCost[s.ID].ToString("C2") }); } }
视图代码修改
@foreach (Site s in sites) { if(s.ShowColumns) { <tr> <td style="font-weight : bold;">@s.Name</td> <td></td> <td></td> <td style="font-weight : bold;">Average Cost</td> <td></td> <td></td> <td style="font-weight : bold;">Average Cost With Labour</td> </tr> } }
方案二:用字典存储每个站点的独立状态
如果无法修改Site类的结构,可以创建一个字典来映射每个站点ID对应的显示状态:
控制器代码修改
// 先创建字典保存每个Site的显示状态 Dictionary<int, bool> siteShowStatus = new Dictionary<int, bool>(); foreach (Site s in sites) { var OffReportRows = new Queue<List<string>>(); bool needShowColumns = osiTotal[s.ID] > 0; siteShowStatus[s.ID] = needShowColumns; if (needShowColumns) { OffReportRows.Enqueue(new List<string> { "Parts", "", "", osiPartCost[s.ID].ToString("C2"), "", "", osiPartCost[s.ID].ToString("C2") }); } } // 将字典存入ViewBag ViewBag.SiteShowStatus = siteShowStatus;
视图代码修改
@foreach (Site s in sites) { var siteShowStatus = ViewBag.SiteShowStatus as Dictionary<int, bool>; if(siteShowStatus != null && siteShowStatus.TryGetValue(s.ID, out bool needShow) && needShow) { <tr> <td style="font-weight : bold;">@s.Name</td> <td></td> <td></td> <td style="font-weight : bold;">Average Cost</td> <td></td> <td></td> <td style="font-weight : bold;">Average Cost With Labour</td> </tr> } }
这两种方案都能让每个站点拥有独立的显示判断条件,彻底解决ViewBag全局覆盖导致的异常问题。
内容的提问来源于stack exchange,提问作者chris
相关产品推荐
相关产品推荐

