30 votes

TextBoxFor vs EditorFor, et htmlAttributes vs additionalViewData

J'ai créé un défaut MVC 3 projet (à l'aide de rasoir), afin de démontrer un problème.

Sur la page de connexion, il y a une ligne:

@Html.TextBoxFor(m => m.UserName)

si je change ce:

@Html.TextBoxFor(m => m.UserName, new { title = "ABC" })

Alors la c'est rendu que (avec un attribut title):

<input data-val="true" data-val-required="The User name field is required." id="UserName" name="UserName" title="ABC" type="text" value="" />

Cependant, si je fais un EditorFor:

 @Html.EditorFor(m => m.UserName, new { title = "ABC" })

Puis il s'est rendu (sans attribut title) comme:

<input class="text-box single-line" data-val="true" data-val-required="The User name field is required." id="UserName" name="UserName" type="text" value="" />

Donc en résumé, l'attribut title est perdu lorsque j'utilise EditorFor.

Je sais que le deuxième paramètre pour TextBoxFor est appelé htmlAttributes, et pour EditorFor il est additionalViewData, mais j'ai vu des exemples où EditorFor peut rendre les attributs fournis avec ce paramètre.

Quelqu'un peut-il expliquer ce que je fais de mal, et comment je peux avoir un attribut title lors de l'utilisation de EditorFor?

14voto

Colin Bowern Points 966

Je crois que j'ai trouvé un peu plus agréable solution. EditorFor prend en additionalViewData en tant que paramètre. Si vous lui donnez un paramètre nommé "htmlAttributes" avec les attributs, alors on peut faire des choses intéressantes avec elle:

@Html.EditorFor(model => model.EmailAddress,
                new { htmlAttributes = new { @class = "span4",
                                             maxlength = 128,
                                             required = true,
                                             placeholder = "Email Address",
                                             title = "A valid email address is required (i.e. user@domain.com)" } })

Dans le modèle (dans ce cas, votre Adresse de courrier électronique.cshtml) vous pouvez alors fournir quelques attributs par défaut:

@Html.TextBox("",
              ViewData.TemplateInfo.FormattedModelValue,
              Html.MergeHtmlAttributes(new { type = "email" }))

La magie vient ensemble par le biais de cette méthode d'assistance:

public static IDictionary<string, object> MergeHtmlAttributes<TModel>(this HtmlHelper<TModel> htmlHelper, object htmlAttributes)
{
    var attributes = htmlHelper.ViewData.ContainsKey("htmlAttributes")
                            ? HtmlHelper.AnonymousObjectToHtmlAttributes(htmlHelper.ViewData["htmlAttributes"])
                            : new RouteValueDictionary();

    if (htmlAttributes != null)
    {
        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(htmlAttributes))
        {
            var key = property.Name.Replace('_', '-');
            if (!attributes.ContainsKey(key))
            {
                attributes.Add(key, property.GetValue(htmlAttributes));
            }
        }
    }

    return attributes;
}

Vous pouvez bien sûr le modifier pour rendre les attributs ainsi si vous faites du HTML brut:

public static MvcHtmlString RenderHtmlAttributes<TModel>(this HtmlHelper<TModel> htmlHelper, object htmlAttributes)
{
    var attributes = htmlHelper.ViewData.ContainsKey("htmlAttributes")
                            ? HtmlHelper.AnonymousObjectToHtmlAttributes(htmlHelper.ViewData["htmlAttributes"])
                            : new RouteValueDictionary();

    if (htmlAttributes != null)
    {
        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(htmlAttributes))
        {
            var key = property.Name.Replace('_', '-');
            if (!attributes.ContainsKey(key))
            {
                attributes.Add(key, property.GetValue(htmlAttributes));
            }
        }
    }

    return MvcHtmlString.Create(String.Join(" ",
        attributes.Keys.Select(key =>
            String.Format("{0}=\"{1}\"", key, htmlHelper.Encode(attributes[key])))));
}

12voto

lko Points 1062

Dans MVC3 vous pouvez ajouter un titre (et d'autres htmlAttributes) à l'aide de ce type de solution de contournement si vous créez une coutume EditorFor modèle. Ce cas est préparé pour que cette valeur soit facultatif, editorFor les appels ne sont pas tenus d'inclure l' object additionalViewData

@Html.EditorFor(m => m.UserName, "CustomTemplate", new { title = "ABC" })

EditorTemplates/CustomTemplate.cshtml

@{
    string s = "";
    if (ViewData["title"] != null) {
        // The ViewData["name"] is the name of the property in the addtionalViewData...
        s = ViewData["title"].ToString();
    }
}

@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { title = s })

J'ai fait quelque chose de très similaire à inclure une option de classe dans un EditorTemplate. Vous pouvez ajouter autant d'articles à la addtionalViewData que vous voulez, mais vous devez les traiter dans le EditorFor modèle.

5voto

Darin Dimitrov Points 528142

Vous pouvez consulter le billet de blog suivant qui illustre comment implémenter un fournisseur de métadonnées personnalisé et utiliser des annotations de données sur votre modèle de vue afin de définir des propriétés html telles que class , maxlength , title , ... Ceci pourrait ensuite être utilisé conjointement avec les modèles d'aide.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X