Bon, je suis conscient que ce n'est pas une réponse directe à votre question, mais cela peut être une meilleure façon de faire la plupart des intrants de toute façon (et c'était amusant à faire). Je viens à peine terminé cette et a couru une petite quantité de tester contre, donc je ne peux pas se porter garant de cet être parfait dans chaque situation.
J'ai eu cette idée de Jimmy Bogard post ici. Prendre un coup d'oeil car il y a un tas d'idées vraiment cool.
Ce que j'ai fait il est créé une "InputFor" helper qui essaie de son mieux de travailler sur l'entrée que vous demandez et les sorties en conséquence. Cela va faire des boutons radio, mais par défaut une liste déroulante si il n'y a plus de deux, vous devriez être en mesure de modifier cette fonctionnalité assez facilement.
Le code ci-dessous permet de faire des appels comme <%= Html.InputFor(m => m.Gender) %>
ou <%Html.InputFor(m => m.Gender, Model.GenderList)%>
. Il y a un peu de fraîcheur peu à la fin qui permet de faire le codage par la convention, mais nous y reviendrons plus tard.
public static MvcHtmlString InputFor<TModel>(this HtmlHelper<TModel> helper, Expression<Func<TModel, object>> field, Dictionary<string, string> 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 <= 2)
{
//This is a good length for a radio button
string output = "";
foreach (KeyValuePair<string, string> 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<string, string>();
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);
}
}
Codage par Convention
Le code ci-dessous permet de le faire avec la convention over configuration à l'esprit. Un exemple de ceci est que si vous avez un modèle objet qui contient la propriété que vous souhaitez ajouter à la liste (le Sexe) et un dictionnaire avec le même nom, mais se terminant par "Liste" (GenderList) puis il va utiliser cette liste par défaut.
par exemple, <%= Html.InputFor(m => m.Gender) %>
peut faire une liste déroulante/groupe de boutons radio, mais ces valeurs par défaut peuvent être remplacés par un appel comme <%= Html.InputFor(m => m.Gender, alternate_list) %>
public static MvcHtmlString InputFor<TModel>(this HtmlHelper<TModel> helper, Expression<Func<TModel, object>> field) where TModel : class
{
string property_name = GetInputName(field) + "List";
PropertyDescriptor list_descriptor = TypeDescriptor.GetProperties(helper.ViewData.Model).Find(property_name, true);
Dictionary<string, string> 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<string, string>)temp.GetValue(helper.ViewData.Model, null);
}
return InputFor(helper, field, listing);
}
Maintenant un léger avertissement:
- Ce n'est pas le plus rapide de code dans le monde (à cause de la réflexion et d'autres choses), dans ma situation, ce n'est pas vraiment pertinente, car elle est tout axé sur l'utilisateur, si vous avez l'intention de faire quelque chose de fou stupide.
- Ce code est à ses balbutiements, je vais tester cela de manière plus approfondie et d'en ajouter au cours des prochains jours, ouvert à toutes suggestions pour améliorer le code.
J'espère que ce code est utile à quelqu'un, je sais que je vais l'utiliser au cours de la prochaine quelques semaines pour essayer et réduire les temps. La coupe de ce vers le bas pour faire juste le bouton radio devrait être une tâche facile, bonne chance :)
Jay