Razor视图Post后如何保留DropdownList选中值?MVC技术求助
解决MVC Razor视图联动DropdownList选中值丢失问题
Hey there, 我刚接触MVC的时候也碰到过一模一样的联动下拉选中值丢失的问题,咱们一步步来搞定它。你的核心问题在于:当通过onchange触发页面刷新时,没有给第一个下拉框(医院)指定选中项,默认会回到列表的第一个选项。
一、快速修复:给DropDownList指定选中值
你现在用的是Html.DropDownList的无强类型重载,只需要在调用时加上选中值参数即可。先修改你的视图代码:
@model testContingency.Models.ListByWardDD @{ ViewBag.Title = "TestDropDowns"; } <h2>TestDropDowns</h2> <div> @Html.DropDownList("HospModel", Model.Hospital, new { @onchange = "ChangeHospital(this.value)" }, Model.SelectedHospID) @Html.DropDownList("WardModel", Model.Wards, Model.SelectedWardID) <script type="text/javascript"> function ChangeHospital(val) { window.location.href = "/PatientListByWardDD/TestDropDowns?hospID=" + val; } </script> </div>
接着,在你的ListByWardDD模型里添加两个属性来保存选中值:
public class ListByWardDD { public IEnumerable<SelectListItem> Hospital { get; set; } public IEnumerable<SelectListItem> Wards { get; set; } // 新增属性用于保存选中的ID public int? SelectedHospID { get; set; } public int? SelectedWardID { get; set; } }
最后修改控制器代码,把传入的hospID赋值给模型的选中属性:
public ActionResult TestDropDowns(int? hospID) { PASInpatientRepository pasRepo = new PASInpatientRepository(); var returnModel = new ListByWardDD(); var HospitalData = pasRepo.GetPatientHospitalsEnum(); returnModel.Hospital = pasRepo.GetHopspitalListItems(HospitalData); // 将传入的医院ID绑定到模型的选中属性 returnModel.SelectedHospID = hospID; var WardData = pasRepo.GetPatientWardsEnum(hospID); returnModel.Wards = pasRepo.GetWardListItems(WardData); return View(returnModel); }
这样修改后,页面刷新时医院下拉框就会自动选中你之前选择的项了。
二、更规范的优化:使用强类型DropDownListFor
既然你提到很多示例是强类型场景,那更推荐用Html.DropDownListFor,这更符合MVC的设计理念,也能减少人为错误:
修改后的视图代码:
@model testContingency.Models.ListByWardDD @{ ViewBag.Title = "TestDropDowns"; } <h2>TestDropDowns</h2> <div> @Html.DropDownListFor(m => m.SelectedHospID, Model.Hospital, "请选择医院", new { @onchange = "ChangeHospital(this.value)" }) @Html.DropDownListFor(m => m.SelectedWardID, Model.Wards, "请选择病房") <script type="text/javascript"> function ChangeHospital(val) { window.location.href = "/PatientListByWardDD/TestDropDowns?hospID=" + val; } </script> </div>
这里DropDownListFor会自动绑定m => m.SelectedHospID作为选中值,不需要手动设置selected属性,简洁又可靠。控制器代码和上面一致,把hospID赋值给returnModel.SelectedHospID即可。
三、进阶优化:用Ajax实现无刷新联动(提升用户体验)
现在的实现是整页刷新,体验不太友好,你可以用Ajax异步加载病房列表,避免整页刷新:
首先修改视图,给下拉框添加ID并引入jQuery:
@model testContingency.Models.ListByWardDD @{ ViewBag.Title = "TestDropDowns"; } <h2>TestDropDowns</h2> <div> @Html.DropDownListFor(m => m.SelectedHospID, Model.Hospital, "请选择医院", new { @id = "hospitalDropdown" }) @Html.DropDownListFor(m => m.SelectedWardID, Model.Wards, "请选择病房", new { @id = "wardDropdown" }) <script src="~/Scripts/jquery-3.6.0.min.js"></script> <script type="text/javascript"> $(function() { $("#hospitalDropdown").change(function() { var hospID = $(this).val(); $.ajax({ url: "/PatientListByWardDD/GetWardsByHospID", type: "GET", data: { hospID: hospID }, success: function(data) { // 清空病房下拉框并添加新选项 $("#wardDropdown").empty(); $("#wardDropdown").append('<option value="">请选择病房</option>'); $.each(data, function(index, item) { $("#wardDropdown").append('<option value="' + item.Value + '">' + item.Text + '</option>'); }); } }); }); }); </script> </div>
然后在控制器里新增一个Action来返回病房的SelectListItem:
public JsonResult GetWardsByHospID(int? hospID) { PASInpatientRepository pasRepo = new PASInpatientRepository(); var WardData = pasRepo.GetPatientWardsEnum(hospID); var wardList = pasRepo.GetWardListItems(WardData); // 返回Json格式的数据供前端使用 return Json(wardList, JsonRequestBehavior.AllowGet); }
这样用户选择医院时,只会异步加载病房列表,页面不会刷新,体验更好,而且选中值也会自动保留。
额外的小建议
- 把
PASInpatientRepository的实例化改成依赖注入(DI),这样代码更易测试和维护,不过这是进阶内容,你可以后续再研究。 - 给下拉框添加默认提示选项(比如"请选择医院"),提升用户体验。
- 控制器里的
ViewBag.HospSearch可以去掉了,因为我们已经用模型的SelectedHospID来保存选中值了。
内容的提问来源于stack exchange,提问作者ChipChipowsky
相关产品推荐
相关产品推荐

