94

有没有办法使用@Html.EditorFor 编写Html5 占位符,或者我应该只使用 TextBoxFor 扩展,即

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

或者编写我们自己的自定义扩展是否有意义,它可以通过 DataAnnotations 使用“描述”显示属性(类似于这个)?

当然,同样的问题也适用于“自动对焦”。

4

7 回答 7

122

正如 Darin Dimitrov 的回答中的 smnbss 评论,Prompt正是为了这个目的而存在的,所以不需要创建自定义属性。从文档中:

获取或设置一个值,该值将用于为 UI 中的提示设置水印。

要使用它,只需像这样装饰视图模型的属性:

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

该文本然后方便地放置在ModelMetadata.Watermark. 开箱即用,MVC 3 中的默认模板忽略该Watermark属性,但使其工作非常简单。你需要做的就是调整默认的字符串模板,告诉 MVC 如何渲染它。只需编辑 String.cshtml,就像 Darin 所做的那样,除了不是从 获取水印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位。

如果您还想为多行文本框 (textareas) 启用水印,请对 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 })
于 2011-07-05T06:01:06.983 回答
69

您可以查看以下文章来编写自定义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>
于 2011-04-28T19:53:38.783 回答
23

我实际上更喜欢在大多数情况下使用占位符文本的显示名称。以下是使用 DisplayName 的示例:

  @Html.TextBoxFor(x => x.FirstName, true, null, new { @class = "form-control", placeholder = Html.DisplayNameFor(x => x.FirstName) })
于 2014-07-17T22:06:56.380 回答
4

我对资源文件使用这种方式(不再需要提示!)

@Html.TextBoxFor(m => m.Name, new 
{
     @class = "form-control",
     placeholder = @Html.DisplayName(@Resource.PleaseTypeName),
     autofocus = "autofocus",
     required = "required"
})
于 2014-12-30T10:24:10.713 回答
3

我写了这样一个简单的类:

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

和视图模型中的属性:

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

注意提示参数。在这种情况下,我使用资源中的字符串进行本地化,但您可以只使用字符串,只需避免使用 ResourceType 参数。

于 2014-10-23T22:02:31.843 回答
1

这是我使用上述想法制作的解决方案,可用于 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));
    }
}
于 2015-05-22T14:21:41.227 回答
0

我认为创建自定义 EditorTemplate 不是一个好的解决方案,因为您需要关心针对不同情况的许多可能的模板:字符串、numsers、组合框等。其他解决方案是自定义扩展 HtmlHelper。

模型:

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

Html 辅助扩展:

   public static MvcHtmlString BsEditorFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TValue>> expression, string htmlClass = "")
{
    var modelMetadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
    var metadata = modelMetadata;

    var viewData = new
    {
        HtmlAttributes = new
            {
                @class = htmlClass,
                placeholder = metadata.Watermark,
            }
    };
    return htmlHelper.EditorFor(expression, viewData);

}

对应的视图:

@Html.BsEditorFor(x => x.Title)
于 2018-10-18T12:56:11.230 回答