Pourquoi ne puis-je pas transmettre d'attributs HTML à EditorFor()
? par exemple;
<%= Html.EditorFor(model => model.Control.PeriodType,
new { disabled = "disabled", readonly = "readonly" }) %>
Je ne veux pas utiliser les métadonnées
Mise à jour: La solution consistait à appeler cela depuis la vue:
<%=Html.EditorFor( model => model.Control.PeriodEndDate, new {Modifiable=model.Control.PeriodEndDateModifiable})%>
et utilisez ViewData["Modifiable"]
dans mon EditorTemplates/String.ascx personnalisé, où j’ai une logique de vue qui détermine s’il faut ajouter des attributs en lecture seule et/ou désactivés à l’entrée. L’objet anonyme transmis à EditorFor()
est un paramètre appelé additionalViewData
et ses propriétés sont transmises au modèle d'éditeur de la collection ViewData
.
EditorFor
fonctionne avec les métadonnées, donc si vous souhaitez ajouter des attributs HTML, vous vous pouvez toujours le faire . Une autre option consiste simplement à écrire un modèle personnalisé et à utiliser TextBoxFor
:
<%= Html.TextBoxFor(model => model.Control.PeriodType,
new { disabled = "disabled", @readonly = "readonly" }) %>
Mise à jour MVC 5.1 prend désormais directement en charge l'approche ci-dessous, de sorte que cela fonctionne également pour l'éditeur intégré. http://www.asp.net/mvc/overview/releases/mvc51-release-notes#new-features (C'est soit un cas de grand esprit qui pense de la même façon, soit ils lisent ma réponse :)
Terminer la mise à jour
Si vous utilisez votre propre modèle d’éditeur ou avec MVC 5.1, qui prend désormais en charge l’approche ci-dessous directement pour les éditeurs intégrés.
@Html.EditorFor(modelItem => item.YourProperty,
new { htmlAttributes = new { @class="verificationStatusSelect", style = "Width:50px" } })
puis dans votre modèle (non requis pour les types simples dans MVC 5.1)
@Html.TextBoxFor(m => m, ViewData["htmlAttributes"])
À partir de MVC 5.1, vous pouvez maintenant effectuer les opérations suivantes:
@Html.EditorFor(model => model, new { htmlAttributes = new { @class = "form-control" }, })
http://www.asp.net/mvc/overview/releases/mvc51-release-notes#new-features
Maintenant ASP.Net MVC 5.1 dispose d’un support intégré.
à partir des notes de publication
Nous autorisons maintenant la transmission d'attributs HTML dans EditorFor en tant qu'objet anonyme.
Par exemple:
@Html.EditorFor(model => model,
new { htmlAttributes = new { @class = "form-control" }, })
Voici la syntaxe code VB.Net pour attributs HTML dans MVC 5.1 EditorFor
@Html.EditorFor(Function(x) x.myStringProp, New With {.htmlAttributes = New With {.class = "myCssClass", .maxlength="30"}}))
Pourquoi ne pas simplement utiliser
@Html.DisplayFor(model => model.Control.PeriodType)
Vous pouvez toujours utiliser EditorFor. Il suffit de passer l'attribut HTML style/whichever comme ViewData.
@Html.EditorFor(model => model.YourProperty, new { style = "Width:50px" })
Étant donné que EditorFor utilise des modèles pour le rendu, vous pouvez remplacer le modèle par défaut de votre propriété et simplement transmettre l'attribut de style en tant que ViewData.
Votre EditorTemplate aimerait donc ce qui suit:
@inherits System.Web.Mvc.WebViewPage<object>
@Html.TextBoxFor(m => m, new { @class = "text ui-widget-content", style=ViewData["style"] })
Si vous ne souhaitez pas utiliser les métadonnées, vous pouvez utiliser un attribut [UIHint("PeriodType")]
pour décorer la propriété ou, s'il s'agit d'un type complexe, vous n'avez rien à décorer. EditorFor recherchera alors un fichier PeriodType.aspx ou ascx dans le dossier EditorTemplates et l'utilisera à la place.
Html.TextBoxFor(model => model.Control.PeriodType,
new { @class="text-box single-line"})
vous pouvez utiliser comme ça; même résultat avec Html.EditorFor
, et vous pouvez ajouter vos attributs html
Dans mon cas, j’essayais de créer un modèle d’éditeur d’entrée au nombre HTML5 pouvant recevoir des attributs supplémentaires. Une approche plus rationnelle consisterait à écrire votre propre HTML Helper, mais comme j'avais déjà mon modèle .ascx, j'ai opté pour cette approche:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<input id="<%= Regex.Replace(ViewData.TemplateInfo.GetFullHtmlFieldId(""), @"[\[\]]", "_") %>" name="<%= ViewData.TemplateInfo.HtmlFieldPrefix %>" type="number" value="<%= ViewData.TemplateInfo.FormattedModelValue %>"
<% if (ViewData["attributes"] != null)
{
Dictionary<string, string> attributes = (Dictionary<string, string>)ViewData["attributes"];
foreach (string attributeName in attributes.Keys){%>
<%= String.Format(" {0}=\"{1}\"", attributeName, attributes[attributeName])%>
<% }
} %> />
Ce bit laid crée une entrée de type nombre et recherche un dictionnaire ViewData avec la clé "attributs". Il parcourera le dictionnaire en ajoutant ses paires clé/valeur en tant qu'attributs. La regex dans l'attribut ID n'a pas de relation et existe car, lorsqu'elle est utilisée dans une collection, GetFullHtmlFieldId()
renvoie un identifiant contenant des crochets []
qu'il échapperait normalement en tant que caractères de soulignement.
Ce modèle s'appelle alors comme ceci:
Html.EditorFor(m => m.Quantity, "NumberField", new { attributes = new Dictionary<string, string>() { { "class", "txtQuantity" } } }
Verbose, mais ça marche. Vous pouvez probablement utiliser la réflexion dans le modèle pour utiliser les noms de propriétés en tant que noms d'attributs au lieu d'utiliser un dictionnaire.
Je me bats avec le même problème aujourd'hui pour une case à cocher qui se lie à un boolé nullable, et comme je ne peux pas changer mon modèle (pas mon code), je devais trouver un meilleur moyen de gérer cela. C'est un peu brutal, mais cela devrait fonctionner dans 99% des cas que je pourrais rencontrer. Il est évident que vous devrez procéder à une génération manuelle d'attributs valides pour chaque type d'entrée, mais je pense que je les ai tous obtenus pour la case à cocher.
Dans mon modèle d'éditeur Boolean.cshtml:
@model bool?
@{
var attribs = new Dictionary<string, object>();
var validAttribs = new string[] {"style", "class", "checked", "@class",
"classname","id", "required", "value", "disabled", "readonly",
"accesskey", "lang", "tabindex", "title", "onblur", "onfocus",
"onclick", "onchange", "ondblclick", "onmousedown", "onmousemove",
"onmouseout", "onmouseover", "onmouseup", "onselect"};
foreach (var item in ViewData)
{
if (item.Key.ToLower().IndexOf("data_") == 0 || item.Key.ToLower().IndexOf("aria_") == 0)
{
attribs.Add(item.Key.Replace('_', '-'), item.Value);
}
else
{
if (validAttribs.Contains(item.Key.ToLower()))
{
attribs.Add(item.Key, item.Value);
}
}
}
}
@Html.CheckBox("", Model.GetValueOrDefault(), attribs)
Définissez la condition à l'aide de ViewData
dans le contrôleur
ViewData["Modifiable"] = model.recProcessed;
Ensuite, utilisez cette viewdata dans le modèle d'éditeur pour définir l'attribut html du contrôle
@Html.RadioButton(prefix, li.Value, li.Selected, @ViewData["Modifiable"].ToString().ToLower() == "true" ? (object)new { @id = li.Value, @disabled = "disabled" } : new { @id = li.Value })
Créez simplement votre propre modèle pour le type dans Views/Shared/EditorTemplates/MyTypeEditor.vbhtml
@ModelType MyType
@ModelType MyType
@Code
Dim name As String = ViewData("ControlId")
If String.IsNullOrEmpty(name) Then
name = "MyTypeEditor"
End If
End Code
' Mark-up for MyType Editor
@Html.TextBox(name, Model, New With {.style = "width:65px;background-color:yellow"})
Invoquez editor depuis votre vue avec la propriété model:
@Html.EditorFor(Function(m) m.MyTypeProperty, "MyTypeEditor", New {.ControlId = "uniqueId"})
Pardonnez la syntaxe VB. C'est comme ça qu'on roule.
Solution MVC 5.1 et supérieure (fusionnera les attributs HTML locaux définis dans les EditorTemplates):
Shared\EditorTemplates\String.cshtml:
@Html.TextBoxFor(model => model, new { @class = "form-control", placeholder = ViewData.ModelMetadata.Watermark }.ToExpando().MergeHtmlAttributes(ViewData["htmlAttributes"].ToExpando()))
Extensions:
public static IDictionary<string, object> MergeHtmlAttributes(this ExpandoObject source1, dynamic source2)
{
Condition.Requires(source1, "source1").IsNotNull().IsLongerThan(0);
IDictionary<string, object> result = source2 == null
? new Dictionary<string, object>()
: (IDictionary<string, object>) source2;
var dictionary1 = (IDictionary<string, object>) source1;
string[] commonKeys = result.Keys.Where(dictionary1.ContainsKey).ToArray();
foreach (var key in commonKeys)
{
result[key] = string.Format("{0} {1}", dictionary1[key], result[key]);
}
foreach (var item in dictionary1.Where(pair => !result.ContainsKey(pair.Key)))
{
result.Add(item);
}
return result;
}
public static ExpandoObject ToExpando(this object anonymousObject)
{
IDictionary<string, object> anonymousDictionary = new RouteValueDictionary(anonymousObject);
IDictionary<string, object> expando = new ExpandoObject();
foreach (var item in anonymousDictionary)
expando.Add(item);
return (ExpandoObject)expando;
}
public static bool HasProperty(this ExpandoObject expando, string key)
{
return ((IDictionary<string, object>)expando).ContainsKey(key);
}
Usage:
@Html.EditorFor(m => m.PromotionalCode, new { htmlAttributes = new { ng_model = "roomCtrl.searchRoomModel().promoCode" }})