How to implement multiple dropdown lists in MVC
Solution 1
I ended up using the EditorTemplate functionality in order to solve / render this.
The Model changed from this:
public class ValueModel
{
public Guid Id { get; set; }
public string Name { get; set; }
}
To this:
public class ValueModel
{
public Guid Id { get; set; }
public string Name { get; set; }
public List<ValueDropDownModel> DropDown { get; set; }
}
public class ValueDropDownModel
{
[Range(0, 15)]
public int DropDown { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public List<SelectListItem> AvailableDropDown { get; set; }
}
Within the Views
under the folder for Value
, there is now a sub folder called EditorTemplates
. This contains 2 Views. A ValueModel.cshtml
and a ValueDropDownModel.cshtml
.
ValueModel.cshtml
contains:
@model SomeSolution.Web.Models.ValueModel
<div class="row-fluid">
<div class="span6">
<div class="control-group">
@Html.LabelFor(m => m.Name)
<div class="controls">
@Html.EditorFor(m => m.Name)
@Html.ValidationMessageFor(m => m.Name)
</div>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span4">
@for (int i = 0; i < 5; ++i)
{
@Html.EditorFor(m => m.DropDown[i])
}
</div>
<div class="span4">
@for (int i = 5; i < 10; ++i)
{
@Html.EditorFor(m => m.DropDown[i])
}
</div>
<div class="span4">
@for (int i = 10; i < 15; ++i)
{
@Html.EditorFor(m => m.DropDown[i])
}
</div>
</div>
ValueDropDownModel.cshtml
contains:
@model SomeSolution.Web.Models.ValueDropDownModel
<div class="control-group">
@Html.HiddenFor(m => m.DropDown)
@String.Format("DropDown {0}", Model.DropDown)
<div class="controls">
@Html.DropDownListFor(m => m.Id, Model.AvailableDropDown)
@Html.ValidationMessageFor(m => m.Id)
</div>
</div>
The ValueController
now includes some helper methods to populate the drop downs
private void FillAvailableValues(ValueModel modelValue, Entities db)
{
var values = (from v in db.Values
orderby v.Name
select v);
foreach (var model in modelValue.Values)
{
model.AvailableDropDown = new List<SelectListItem>();
model.AvailableDropDown.Add(new SelectListItem()
{
Text = "Unassigned",
Value = "0",
Selected = (model.Id == 0)
});
foreach (var value in values)
{
model.AvailableDropDown.Add(new SelectListItem()
{
Text = value.Name,
Value = value.Id,
Selected = (model.Id.ToString() == colour.Id)
});
}
}
}
private void InitDefaultDropDown(ValueModel model)
{
model.DropDown = new List<ValueDropDownModel>();
for (int i = 0; i < 15; i++)
{
model.DropDown.Add(new ValueDropDownModel()
{
DropDown = i + 1,
Id = 0
});
}
}
The FillAvailableValues
method is called on the Create
ActionResult
as well as the Edit
ActionResult
to initialize the Drop Downs. The InitDefaultDropDown
method is called on the Create
ActionResult
to setup the Drop Downs on the page.
Solution 2
You can re-use the select list - just use the proper overlad of DropDownList
or DropDownListFor
. What you should (normally) do is give the dropdowns different names.
For example:
@Html.DropDownListFor( m => m.PickedValue1, ViewBag.Values)
@Html.DropDownListFor( m => m.PickedValue2, ViewBag.Values)
Or, if you prefer the non-strongly typed DropDownList
:
@Html.DropDownList( "PickedValue1", ViewBag.Values)
@Html.DropDownList( "PickedValue2", ViewBag.Values)
iamchrisfryer
Programming: HTML, JavaScript, CSS, Java/JSP, XML, C#, PHP, jQuery Database: SQL Server 2000, T-SQL, SQL Server 2005, SQL Server Analysis Services, SQL Server 2008, SQL Azure, MySql Methodologies: SDLC, n-tier architecture, Object Oriented Design, Agile Development/XP/TDD, MVC3, MVC4, MVC5, Entity Framework 4.0 Applications: VS 2005/2008/2010/2012, Java NetBeans 3.6, Facebook, Twitter, MS Office XP/2003/2007/2010, JIRA, Subversion (SVN), CruiseControl, MS SharePoint, MercurialHg, Git, Perforce, SourceTree
Updated on June 07, 2022Comments
-
iamchrisfryer about 2 years
Let's say I want to show multiple Drop Down Boxes each with the same values within them within a View using the @Html.DropDownList. Is there an easy way to be able to render all of these Drop Down Boxes without having to bind something like the ViewBag to each of the months returned?
For example:
Controller
List<SelectListItem> items = new List<SelectListItem>(); var values = (from v in db.Values select v); foreach (var value in values) { items.Add(new SelectListItem { Text = value.Name, Value = value.Id }); } ViewBag.Values = PopulateSelectList("Values");
View
@Html.DropDownList("Values")
But what the goal would be is to have something like
<div class="control-group"> @Html.LabelFor(model => model.DesignStyle) <div class="controls"> @Html.DropDownList("Values") @Html.DropDownList("Values") @Html.DropDownList("Values") @Html.DropDownList("Values") @Html.DropDownList("Values") @Html.DropDownList("Values") @Html.DropDownList("Values") @Html.DropDownList("Values") @Html.DropDownList("Values") @Html.DropDownList("Values") </div> </div>
My guess is I would need some sort of
@foreach (item in Model)
to populate each of the DropDowns on the ViewHere is a sample of my initial thought on how to get something going.
List<SelectListItem> results = new List<SelectListItem>(); SelectListItem item = null; var values = (from v in db.Values select v); for (int i = 0; i <= 15; i++) { item = new SelectListItem(); item.Text = "Select a value"; item.Value = "1"; results.Add(item); foreach (var thread in threads) { item.Text = thread.Name; item.Value = thread.Id; results.Add(item); } }
What I don't want to do is duplicate the logic to populate a SelectListItem multiple times and put each of those in a separate ViewBag item.