web-dev-qa-db-ja.com

.NET MVC 3 Razor Editorを使用したHtml5プレースホルダー

@ -Html.EditorForを使用して Html5プレースホルダー を記述する方法はありますか、それともTextBoxFor拡張機能、つまり.

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

または、DataAnnotationsを介して 'Description'表示属性を使用できる独自のカスタム拡張機能を記述するのは理にかなっています( this と同様)。

もちろん、同じ質問が「オートフォーカス」にも当てはまります。

91
seekay

カスタムDataAnnotationsModelMetadataProviderの記述については、 次の記事 をご覧ください。

そして、新たに導入された IMetadataAware インターフェースを使用したASP.NET MVC 3ishのもう1つの方法があります。

このインターフェイスを実装するカスタム属性を作成することから始めます。

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>
68
Darin Dimitrov

Darin Dimitrovの回答でsmnbssがコメントしているように、Promptはまさにこの目的のために存在するため、カスタム属性を作成する必要はありませんがあります。ドキュメントから:

UIのプロンプトにウォーターマークを設定するために使用される値を取得または設定します。

それを使用するには、ビューモデルのプロパティを次のように装飾します。

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

このテキストはModelMetadata.Watermarkに配置されます。デフォルトでは、MVC 3のデフォルトテンプレートはWatermarkプロパティを無視しますが、動作させるのは非常に簡単です。必要なのは、デフォルトの文字列テンプレートを微調整して、MVCにそのレンダリング方法を指示することだけです。 Darinと同じように、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ビットです。

複数行のテキストボックス(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 })
120
Daniel Liuzzi

実際には、ほとんどの場合、プレースホルダーテキストに表示名を使用することを好みます。 DisplayNameの使用例を次に示します。

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

リソースファイルでこの方法を使用します(プロンプトはもう必要ありません!)

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

このような単純なクラスを作成しました。

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パラメーターは使用しないでください。

3
Mike Eshva

以下は、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));
    }
}
1
Vladimir

カスタムEditorTemplateを作成することは、さまざまなケース(文字列、数値、コンボボックスなど)の多くの可能なtepmlateに注意する必要があるため、良いソリューションではないと思います。他の解決策は、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)
0
Sel