Is there any way to say my view model property should be rendered as DropDownList
(so that I can specify DropDownList
items)?
I have found a lot of custom implementations but I guess there should be a built-in way to implement such a basic thing.
Update. I am rendering my model by Html.EditorForModel
method, I don't want to use methods like Html.DropDownListFor
There's no built-in template which renders a dropdown list, except for the Nullable<bool>
type which renders a Not Set
, Yes
, No
dropdown but I assume that's not what you are asking about.
So let's build one. As always we start by defining the view model that will represent a dropdown containing 2 properties (one for the selected value and one for the available values):
public class ItemViewModel
{
public string SelectedId { get; set; }
public IEnumerable<SelectListItem> Items { get; set; }
}
then we could have a standard view model with this property:
public class MyViewModel
{
public ItemViewModel Item { get; set; }
}
then a controller that will fill the view model:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
Item = new ItemViewModel
{
SelectedId = "2",
Items = new[]
{
new SelectListItem { Value = "1", Text = "item 1" },
new SelectListItem { Value = "2", Text = "item 2" },
new SelectListItem { Value = "3", Text = "item 3" },
}
}
};
return View(model);
}
}
and a corresponding view (~/Views/Home/Index.cshtml
):
@model MyViewModel
@using (Html.BeginForm())
{
@Html.EditorForModel()
}
Now all that's left is to define a custom editor template for the DropDownViewModel
type (~/Views/Shared/EditorTemplates/DropDownViewModel.cshtml
):
@model DropDownViewModel
@Html.DropDownListFor(
x => x.SelectedId,
new SelectList(Model.Items, "Value", "Text", Model.SelectedId)
)
and override the default template for the Object type in order to allow Deep Dive as Brad Wilson explains in his blog post
. Otherwise by default ASP.NET MVC won't recurse into complex subtypes for your templates. So we override ~/Views/Shared/EditorTemplates/Object.cshtml
:
@foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForEdit && !ViewData.TemplateInfo.Visited(pm)))
{
if (prop.HideSurroundingHtml)
{
@Html.Editor(prop.PropertyName)
}
else
{
<div class="editor-label">
@(prop.IsRequired ? "*" : "")
@Html.Label(prop.PropertyName)
</div>
<div class="editor-field">
@Html.Editor(prop.PropertyName)
@Html.ValidationMessage(prop.PropertyName, "*")
</div>
}
}
You could use Html Helper DropDownList to build your drop down list but the model object should be inumerable of SelectionListItem.
//on controller
List<SelectListItem> items = new List<SelectListItem>();
items.Add(new SelectListItem { Text = "Action", Value = "0"});
items.Add(new SelectListItem { Text = "Drama", Value = "1" });
items.Add(new SelectListItem { Text = "Comedy", Value = "2", Selected = true });
items.Add(new SelectListItem { Text = "Science Fiction", Value = "3" });
ViewBag.MovieType = items;
//on view
@Html.DropDownList("MovieType")
If you do not want to build your Model object as SelectListItem, then you should use DropDownListFor
//you can use DropDownListFor as
@Html.DropDownListFor(m=>m.Text,m.Value)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With