Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Okay, I'm aware this isn't a direct answer to your question, but this may be a better way to doing most inputs anyway (and it was fun to make). I have only just completed this and ran a small amount of testing against it, so I can't vouch for this being perfect in every situation.</p> <p>I got this idea from Jimmy Bogard's post <a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/04/24/how-we-do-mvc.aspx" rel="nofollow noreferrer">here</a>. Take a look because there's a heap of really cool ideas there.</p> <p>What I have done is created an "InputFor" helper which tries its best to work out what input you're asking for and outputs it accordingly. This will do radio buttons, but will default to a drop down if there is more than two, you should be able to change this functionality quite easily.</p> <p>The below code allows you to make calls such as <code>&lt;%= Html.InputFor(m =&gt; m.Gender) %&gt;</code> or <code>&lt;%Html.InputFor(m =&gt; m.Gender, Model.GenderList)%&gt;</code>. There is a cool little bit at the end which allows you to do coding by convention, but we'll get to that later.</p> <pre><code>public static MvcHtmlString InputFor&lt;TModel&gt;(this HtmlHelper&lt;TModel&gt; helper, Expression&lt;Func&lt;TModel, object&gt;&gt; field, Dictionary&lt;string, string&gt; listing) where TModel : class { string property_name = GetInputName(field); PropertyDescriptor descriptor = TypeDescriptor.GetProperties(helper.ViewData.Model).Find(property_name, true); string property_type = descriptor.PropertyType.Name; var func = field.Compile(); var value = func(helper.ViewData.Model); //Add hidden element if required if (descriptor.Attributes.Contains(new HiddenInputAttribute())) { return helper.Hidden(property_name, value); } if (property_type == "DateTime" || property_type == "Date") { return helper.TextBox(property_name, value, new { @class = "date_picker" }); } if (listing != null) { if (listing.Count &lt;= 2) { //This is a good length for a radio button string output = ""; foreach (KeyValuePair&lt;string, string&gt; pair in listing) { TagBuilder label = new TagBuilder("label"); label.MergeAttribute("for", property_name); label.SetInnerText(pair.Value); output += helper.RadioButton(property_name, pair.Key, (value == pair.Key)).ToHtmlString(); output += label.ToString(); } return MvcHtmlString.Create(output); } else { //too big for a radio button, lets make a drop down return helper.DropDownList(property_name, new SelectList(listing, "Key", "Value"), value); } } else { if (property_type == "Boolean") { listing = new Dictionary&lt;string, string&gt;(); listing.Add("true", "Yes"); listing.Add("false", "No"); SelectList select_values = new SelectList(listing, "Key", "Value", ((bool)value ? "Yes" : "No")); return helper.DropDownList(property_name, select_values); } return helper.TextBox(property_name, value); } } </code></pre> <h2>Coding by Convention</h2> <p>The below code allows this to be done with convention over configuration in mind. An example of this is if you have a model object which contains the property you want to list (Gender) and a dictionary with the same name but appended with "List" (GenderList) then it will use this list by default.</p> <p>e.g. <code>&lt;%= Html.InputFor(m =&gt; m.Gender) %&gt;</code> can make a full drop down list/radio button group, but these default values can be overridden by making a call like <code>&lt;%= Html.InputFor(m =&gt; m.Gender, alternate_list) %&gt;</code></p> <pre><code>public static MvcHtmlString InputFor&lt;TModel&gt;(this HtmlHelper&lt;TModel&gt; helper, Expression&lt;Func&lt;TModel, object&gt;&gt; field) where TModel : class { string property_name = GetInputName(field) + "List"; PropertyDescriptor list_descriptor = TypeDescriptor.GetProperties(helper.ViewData.Model).Find(property_name, true); Dictionary&lt;string, string&gt; listing = null; if (list_descriptor != null) { //Found a match for PropertyNameList, try to pull it out so we can use it PropertyInfo temp = helper.ViewData.Model.GetType().GetProperty(property_name); listing = (Dictionary&lt;string, string&gt;)temp.GetValue(helper.ViewData.Model, null); } return InputFor(helper, field, listing); } </code></pre> <p>Now a slight disclaimer: </p> <ul> <li>This isn't the fastest code in the world (due to the reflection and other things), in my situation this isn't really relevant as it's all user driven, if you're planning on doing something crazy stupid.</li> <li>This code is in its infancy, I will be testing this more thoroughly and adding to it over the next few days, open to any suggestions to improve the code.</li> </ul> <p>I hope this code is useful to someone, I know I'll be using it over the next couple of weeks to try and cut down time. Cutting this down to just do the radio button should be a trivial task, good luck :)</p> <p>Jay</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload