I have a form, which includes three dynamic dropdownlists. They are all one-to-many relationships. The first dropdownlist has loaded values and the other two are empty at the start. When user selects one value from the 1st dropdownlist, the 2nd dropdownlist will load corresponding items; when user selects a value from the 2nd dropdownlist, the 3rd dropdownlist will load relating items.
User can create the form and submit. My CreateController GET and POST methods works well.
Now I need EditController to allow user to edit his form. The problem is how to display the 2nd and the 3rd dynamic dropdownlist with selected values?
In my viewModel:
public Nullable<int> Tech_ID { get; set; }
public string TechniqueName { get; set; }
public SelectList Techniques { get; set; }
public Nullable<int> BU_ID { get; set; }
public string BuName { get; set; }
public SelectList BusinessUnits { get; set; }
In my Edit Controller:
ViewBag.Bulist = new SelectList(AllBus, "BU_ID", "BU_Title", form.BU_ID);
var butechList = GetTechList(Convert.ToInt32(form.BU_ID));
IEnumerable<SelectListItem> butechs = butechList.Select(m => new SelectListItem()
{
Value = m.Tech_ID.ToString(),
Text = m.Technique.Tech_Title
});
ViewBag.Techlist = new SelectList(butechs, "Tech_ID", "Tech_Title", form.Tech_ID);
in View page:
@Html.DropDownListFor(model => model.BU_ID,
new SelectList((IEnumerable<SelectListItem>)@ViewBag.Bulist, "Value", "Text", Model.BU_ID),
new { id = "ddlBU" })
@Html.DropDownListFor(model => model.Tech_ID,
new SelectList((IEnumerable<SelectListItem>)@ViewBag.Techlist, "Value", "Text", Model.Tech_ID),
new { id = "ddlTechs" })
The first dropdownlist is working correctly, but the second is not.
Firstly, you have a view model containing SelectList
properties, so make use of it rather than using ViewBag
properties.
Next, delete the unnecessary last parameter (object selectedValue
) in you SelectList
constructors - your binding to a property in your model so it is ignored (internally the DropDwonListFor()
method generated a new IEnumerable<SelectListItem>
and sets the selectedValue
based on the value of the property your binding to)
But the main issue is that your unnecessarily generating 3 IEnumerable<SelectListItem>
. The first using
IEnumerable<SelectListItem> butechs = butechList.Select(...
which is correct. Then you try and create another one form it using
ViewBag.Techlist = new SelectList(butechs, "Tech_ID", "Tech_Title", form.Tech_ID);
but this time it will throw an exception because butechs
is IEnumerable<SelectListItem>
and SelectListItem
does not contain properties Tech_ID
and Tech_Title
(it would need to be new SelectList(butechs, "Value", "Text")
to prevent the error, but its pointless so just delete it). And then you try to create a 3rd IEnumerable<SelectListItem>
inside the DropDownListFor()
method (again its pointless extra ovehead).
Your code in the controller simply needs to be
var butechList = GetTechList(form.BU_ID.Value); // its already an int!
model.Techniques = new SelectList(butechList, "Tech_ID", "Tech_Title");
return View(model);
and in the view
@Html.DropDownListFor(m => m.Tech_ID, Model.Techniques) // not sure why you would need to change the id from the default id="Tech_ID" to id="ddlBU"?
I also suggest you study the code in this DotNetFiddle which shows an example of generating cascading dropdownlists. In particular the code in the private void ConfigureViewModel(ViewModel model)
method, which will generate the correct SelectList
's based on selected values, and can be called from both the Create()
and Edit()
methods (both the GET and the POST if you need to return the view)