Html5 Заполнители с .NET MVC 3 Razor EditorДля расширения?

Есть ли способ написать Html5 placeholder с помощью @Html.EditorFor или просто использовать расширение TextBoxFor i.e.

@Html.TextBoxFor(model => model.Title, new { @placeholder = "Enter title here"})

Или было бы целесообразно написать собственное собственное расширение, которое может использовать атрибут отображения "Описание" через DataAnnotations (аналогично this)?

Конечно, тот же вопрос относится и к "автофокусу".

Ответ 1

Вы можете посмотреть следующую статью для написания пользовательского DataAnnotationsModelMetadataProvider.

И вот еще один, более простой способ ASP.NET MVC 3ish, связанный с новым интерфейсом IMetadataAware.

Начните с создания настраиваемого атрибута, реализующего этот интерфейс:

public class PlaceHolderAttribute : Attribute, IMetadataAware
{
    private readonly string _placeholder;
    public PlaceHolderAttribute(string placeholder)
    {
        _placeholder = placeholder;
    }

    public void OnMetadataCreated(ModelMetadata metadata)
    {
        metadata.AdditionalValues["placeholder"] = _placeholder;
    }
}

И затем украсьте своей моделью:

public class MyViewModel
{
    [PlaceHolder("Enter title here")]
    public string Title { get; set; }
}

Далее определите контроллер:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel());
    }
}

Соответствующий вид:

@model MyViewModel
@using (Html.BeginForm())
{
    @Html.EditorFor(x => x.Title)
    <input type="submit" value="OK" />
}

И, наконец, шаблон редактора (~/Views/Shared/EditorTemplates/string.cshtml):

@{
    var placeholder = string.Empty;
    if (ViewData.ModelMetadata.AdditionalValues.ContainsKey("placeholder"))
    {
        placeholder = ViewData.ModelMetadata.AdditionalValues["placeholder"] as string;
    }
}
<span>
    @Html.Label(ViewData.ModelMetadata.PropertyName)
    @Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { placeholder = placeholder })
</span>

Ответ 2

Как комментарии smnbss в ответе Дарина Димитрова, Prompt существует именно для этой цели, поэтому не нужно создавать настраиваемый атрибут. Из документации:

Получает или задает значение, которое будет использоваться установить водяной знак для подсказок в пользовательский интерфейс.

Чтобы использовать его, просто украсьте свое свойство модели просмотра следующим образом:

[Display(Prompt = "numbers only")]
public int Age { get; set; }

Этот текст удобно разместить в ModelMetadata.Watermark. Из-за поля шаблон по умолчанию в MVC 3 игнорирует свойство Watermark, но делает его работу очень простой. Все, что вам нужно сделать, это настроить шаблон строки по умолчанию, чтобы сообщить MVC, как его отображать. Просто отредактируйте String.cshtml, как это делает Дарин, за исключением того, что вместо получения водяного знака от ModelMetadata.AdditionalValues вы получите его прямо из ModelMetadata.Watermark:

~/Views/Shared/EditorTemplates/String.cshtml:

@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "text-box single-line", placeholder = ViewData.ModelMetadata.Watermark })

И это все.

Как вы можете видеть, ключ для работы - бит placeholder = ViewData.ModelMetadata.Watermark.

Если вы также хотите включить водяные знаки для многострочных текстовых полей (текстовые поля), вы делаете то же самое для MultilineText.cshtml:

~/Views/Shared/EditorTemplates/MultilineText.cshtml:

@Html.TextArea("", ViewData.TemplateInfo.FormattedModelValue.ToString(), 0, 0, new { @class = "text-box multi-line", placeholder = ViewData.ModelMetadata.Watermark })

Ответ 3

Я предпочитаю использовать отображаемое имя для текста заполнителя в большинстве случаев. Ниже приведен пример использования DisplayName:

  @Html.TextBoxFor(x => x.FirstName, true, null, new { @class = "form-control", placeholder = Html.DisplayNameFor(x => x.FirstName) })

Ответ 4

Я написал такой простой класс:

public static class WatermarkExtension
{
    public static MvcHtmlString WatermarkFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
    {
        var watermark = ModelMetadata.FromLambdaExpression(expression, html.ViewData).Watermark;
        var htmlEncoded = HttpUtility.HtmlEncode(watermark);
        return new MvcHtmlString(htmlEncoded);
    }
}

Использование как таковое:

@Html.TextBoxFor(model => model.AddressSuffix, new {placeholder = Html.WatermarkFor(model => model.AddressSuffix)})

И свойство в viewmodel:

[Display(ResourceType = typeof (Resources), Name = "AddressSuffixLabel", Prompt = "AddressSuffixPlaceholder")]
public string AddressSuffix
{
    get { return _album.AddressSuffix; }
    set { _album.AddressSuffix = value; }
}

Параметр уведомления. В этом случае я использую строки из ресурсов для локализации, но вы можете использовать только строки, просто избегайте параметра ResourceType.

Ответ 5

Я использую этот путь с файлом ресурсов (больше не требуется "Спрашивать"!)

@Html.TextBoxFor(m => m.Name, new 
{
     @class = "form-control",
     placeholder = @Html.DisplayName(@Resource.PleaseTypeName),
     autofocus = "autofocus",
     required = "required"
})

Ответ 6

Вот решение, которое я сделал с использованием вышеупомянутых идей, которые можно использовать для TextBoxFor и PasswordFor:

public static class HtmlHelperEx
{
    public static MvcHtmlString TextBoxWithPlaceholderFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        return htmlHelper.TextBoxFor(expression, htmlAttributes.AddAttribute("placeholder", metadata.Watermark));

    }

    public static MvcHtmlString PasswordWithPlaceholderFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        return htmlHelper.PasswordFor(expression, htmlAttributes.AddAttribute("placeholder", metadata.Watermark));

    }
}

public static class HtmlAttributesHelper
{
    public static IDictionary<string, object> AddAttribute(this object htmlAttributes, string name, object value)
    {
        var dictionary = htmlAttributes == null ? new Dictionary<string, object>() : htmlAttributes.ToDictionary();
        if (!String.IsNullOrWhiteSpace(name) && value != null && !String.IsNullOrWhiteSpace(value.ToString()))
            dictionary.Add(name, value);
        return dictionary;
    }

    public static IDictionary<string, object> ToDictionary(this object obj)
    {
        return TypeDescriptor.GetProperties(obj)
            .Cast<PropertyDescriptor>()
            .ToDictionary(property => property.Name, property => property.GetValue(obj));
    }
}