web-dev-qa-db-fra.com

Attributs HTML pour EditorFor () dans ASP.NET MVC

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.

126
Typo Johnson

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" }) %>    
96
Darin Dimitrov

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"])
115
AntonK

À 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

42
vtforester

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" }, })
6
Murali Murugesan

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"}}))
4
Max

Pourquoi ne pas simplement utiliser

@Html.DisplayFor(model => model.Control.PeriodType)
3
Mhoque

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"] })
2
user394749

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.

2
John Farrell
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

1
zamoldar

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.

1
xr280xr

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)
1
Isochronous

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 })
1
reine varghese

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.

1
Darrel Lee

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" }})
0
Sergey