TextBoxFor против EditorFor и htmlAttributes против AdditionalViewData - PullRequest
30 голосов
/ 14 июня 2011

Я создал проект MVC 3 по умолчанию (с использованием бритвы), чтобы продемонстрировать проблему.

На странице входа есть строка:

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

, если яизмените это на:

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

Затем оно будет отображено как (с атрибутом title):

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

Однако, если я сделаю это EditorFor:

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

Затем он отображается (без атрибута title) как:

<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="" />

Таким образом, в итоге атрибут title теряется при использовании EditorFor.

Я знаю, что второй параметр для TextBoxFor называется htmlAttributes, а для EditorFor - это AdditionalViewData, однако я видел примеры, когда EditorFor может отображать атрибуты, поставляемые с этим параметром.

Может кто-нибудь пожалуйстаобъясните, что я делаю неправильно, и как я могу иметь атрибут title при использовании EditorFor?

Ответы [ 3 ]

14 голосов
/ 16 июля 2012

Я думаю, что нашел более приятное решение. EditorFor принимает в качестве параметра дополнительные ViewData. Если вы дадите ему параметр с именем "htmlAttributes" с атрибутами, то мы сможем сделать с ним интересные вещи:

@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)" } })

В шаблоне (в данном случае EmailAddress.cshtml) вы можете указать несколько атрибутов по умолчанию:

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

Магия объединяется с помощью этого вспомогательного метода:

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;
}

Конечно, вы можете изменить его для отображения атрибутов, если вы делаете необработанный HTML:

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])))));
}
12 голосов
/ 02 сентября 2011

В MVC3 вы можете добавить заголовок (и другие htmlAttributes), используя этот вид обходного пути, если вы создаете пользовательский шаблон EditorFor. Этот случай подготовлен для необязательного значения, вызовы editorFor не обязаны включать 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 })

Я сделал нечто очень похожее, чтобы включить необязательный класс в EditorTemplate. Вы можете добавить столько элементов в addtionalViewData, сколько захотите, но вам нужно обрабатывать каждый из них в шаблоне EditorFor.

5 голосов
/ 14 июня 2011

Вы можете взглянуть на следующую запись в блоге , которая иллюстрирует, как реализовать пользовательский поставщик метаданных и использовать аннотации данных в вашей модели представления для определения свойств html, таких как class, maxlength, title, ... Это может быть использовано вместе с шаблонными помощниками.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...