@Html.DropDownListFor绑定Entity Framework时无ViewModel属性提示
问题根源
你遇到的智能提示不生效问题,核心有两个原因:
- 视图顶部声明的
Model是IEnumerable<MvcPayroll.Models.HoursView>集合类型,不是单个HoursView实例,所以输入Model.时只会提示集合的属性/方法,不会显示HoursView的内部字段 - 你把公司下拉选项的
Companies集合塞到了每个行级的HoursView对象里,不仅重复冗余,也不符合全局筛选下拉的使用场景
解决步骤
1. 新增父级视图模型
专门承载当前页面的筛选参数、下拉选项、展示数据三类内容:
public class HoursListViewModel { // 筛选用的选中公司ID public int? SelectedCompanyId { get; set; } // 全局公司下拉选项 public IEnumerable<SelectListItem> Companies { get; set; } // 要展示的工时数据列表 public List<HoursView> HoursList { get; set; } }
2. 调整控制器GET逻辑
不用在每个行对象里重复生成下拉选项,统一放到父视图模型中,同时增加筛选逻辑:
// 下拉选项只查一次即可 var companies = (from company in _context.Company select new SelectListItem { Value = company.CompanyID.ToString(), Text = company.CompanyName }).ToList(); // 原始工时查询逻辑 var requiresHoursQuery = from company in _context.Company join employee in _context.Employees on company.CompanyID equals employee.CompanyID join hours in _context.EmployeeHours on employee.EmployeeID equals hours.EmployeeID into hourEmployeees from subHours in hourEmployeees.DefaultIfEmpty() where (employee.EmployeeType == "Hourly" || employee.EmployeeType == "Tips") && (employee.EmployeeStatus == "Active") orderby employee.CompanyID, employee.EmployeeID select new HoursView { CompanyID = company.CompanyID, CompanyName = company.CompanyName, EmployeeID = employee.EmployeeID, EmployeeName = employee.EmployeeName, WeekEndingDate = subHours == null ? dateEndingWeek : subHours.WeekEndingDate, HoursWorked = subHours == null ? 0 : subHours.HoursWorked, Tips = subHours.Tips == null ? 0 : subHours.Tips, Tips_Cash = subHours.Tips_Cash == null ? 0 : subHours.Tips_Cash }; // 选中公司时触发筛选,selectedCompanyId可以加到GET动作的入参里 if(selectedCompanyId.HasValue) { requiresHoursQuery = requiresHoursQuery.Where(h => h.CompanyID == selectedCompanyId.Value); } // 组装返回给视图的模型 var viewModel = new HoursListViewModel { Companies = companies, HoursList = await requiresHoursQuery.ToListAsync() }; return View(viewModel);
3. 修改Razor视图
调整模型声明、下拉绑定、列表遍历逻辑:
@model MvcPayroll.Models.HoursListViewModel @{ ViewData["Title"] = "Index"; } <h1>Index</h1> <!-- 单独做筛选表单,用GET更符合筛选场景 --> @using (Html.BeginForm("Index","EmployeeHours",FormMethod.Get)) { @Html.DropDownListFor(x => x.SelectedCompanyId, Model.Companies, "全部公司") <button type="submit">筛选</button> } <!-- 原有保存表单 --> @using (Html.BeginForm("Index","EmployeeHours",FormMethod.Post)) { <table class="table"> <thead> <tr> <th> @Html.DisplayNameFor(model => model.HoursList.First().CompanyID) </th> <th> @Html.DisplayNameFor(model => model.HoursList.First().EmployeeID) </th> <th> @Html.DisplayNameFor(model => model.HoursList.First().WeekEndingDate) </th> <th> @Html.DisplayNameFor(model => model.HoursList.First().HoursWorked) </th> <th> @Html.DisplayNameFor(model => model.HoursList.First().Tips) </th> <th> @Html.DisplayNameFor(model => model.HoursList.First().Tips_Cash) </th> <th></th> </tr> </thead> <tbody> @foreach (var item in Model.HoursList) { <tr> <td> @Html.DisplayFor(modelItem => item.CompanyName) </td> <td> @Html.DisplayFor(modelItem => item.EmployeeName) </td> <td> @Html.DisplayFor(modelItem => item.WeekEndingDate) </td> <td> @Html.EditorFor(modelItem => item.HoursWorked) </td> <td> @Html.EditorFor(modelItem => item.Tips) </td> <td> @Html.EditorFor(modelItem => item.Tips_Cash) </td> </tr> } </tbody> </table> <p><input type="submit" value="Save" /></p> <p style="color:green; font-size:12px;"> @ViewBag.Message </p> }
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

