My standard way to work with dropdown box in ASP.NET MVC – 2 steps (or 3 if you want to add long description)
I have written a small post about dropdownlist template in ASP.NET MVC here : http://msprogrammer.serviciipeweb.ro/2010/05/30/mvc-helper-templates/
I think that the dropdownlist should be explained more – aand the example will be :
First, let’s say we have Employee and Department. And we have Employee that has a field, named IDDepartment.
When edit/create a user we want to display a dropdownlist for Department in order for the user to choose the department.
Step 1 : obtain from database a list of departments and transform into List<KeyValuePair<string,string>> – where the first string is DepartmentID and the second is Department Name.
Let’s say there is a method to do that : deptList.Values
Step 2 : display into the aspx/ascx file with List_KVP template
<%: Html.EditorFor(model => model.deptList.Values, “List_KVP”, “IDDepartment”, new { SelectedValue = Model.emp.IDDepartment })%>
Here is the weak part: the “IDDepartment” is not strongly typed. You can transform that …but it requires writing another extension. However, when you modify the code for
SelectedValue = Model.emp.IDDepartment
it is right nearby…
For reference, here is the List_KVP.ascx
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<List<System.Collections.Generic.KeyValuePair<string,string>>>" %> <% string Val = "",style=""; if(ViewData.Values != null && ViewData.Values.Count > 0) { Val = (ViewData["SelectedValue"]??"").ToString(); style = (ViewData["Style"] ?? "").ToString(); } if (style.Length > 0) { } var id=ViewData.TemplateInfo.GetFullHtmlFieldId("") ; id = id + ""; %> <select id="<%:id %>" name="<%:ViewData.TemplateInfo.GetFullHtmlFieldName("") %>" style="<%: style %>"> <% foreach (var val in Model) { %> <option value='<%: val.Key %>' <%:(val.Key == Val)?"selected=selected":"" %>><%: val.Value %></option> <%} %> </select> <% if(Model.Exists(x=>x.Key ==Val) ) { %> <script type="text/javascript"> $(document).ready(function () { $('#<%:id %>').change(); } ); </script> <% } %>
Oh, and if you ask how to add a description , nothing more simple :
Step1 : add to dropdown an onchange event : onchange=’javascript:funcDepartmentRetrieve(this)”
Step 2: create a java script function that retrieves the long description from the id
<script type="text/javascript"> <%: Html.JavaScriptFind( Model.deptList.LongDescriptionValues, "funcDepartmentLong","notfoundDepartment") %> </script>
Step 3 : Mix the 2 javascript functions
For your reference, the code for JavaScriptFind is
public static MvcHtmlString JavaScriptFind(this HtmlHelper hh, ICollection<KeyValuePair<string,string>> values, string Name, string NotFound) { string s = "function " + Name + "(value){ switch(value){"; string ret = "case '{0}' : return '{1}';" + Environment.NewLine; foreach (var item in values) { //TODO : compensate for ' s += string.Format(ret, item.Key, item.Value); }; s += string.Format("default : return '{0}' ;//+ value;" + Environment.NewLine, NotFound); s += "};";//switch s += "}";//function return MvcHtmlString.Create(s); }
And you don’t think there are any code smells in there ?
I could name ViewData usage as one. Magic strings anyone?. Hardcoded javascript WTF 😮
You should have a DropDownListViewModel with all existing ViewData values.
What do you do when you have more then one ListView on the page? How do you pass those values to the user control ? do you create inside you html page a ViewDataDictionary to be passed in RenderControl?
I would not recommend this to anyone. If this is the standard you work in… I would not want to be the one who has to maintain the project after you’ve abandoned it.
I was looking for this coding since from many days. I am glad to have found this post. Thanks. Keep posting!
Mihai
I do not think so. The purpose of re-using templates is very near of the MVC
More, I do not see where do you think I have “hardcoded javascript” .
And for your remark about ViewData – please think again. ViewData is hardcoded ….
For passing more than 1 ListView- I will have in my ViewModel more
> – that’s the purpose of a ViewModel!
How I pass those values ? I will have the View inherit from the ViewModel and pass via Html.EditorFor – shown in the post.
About not recommending – your choice. After you have done testing with ViewData for dropdownlist, please come back and test my code…