Html5 Platzhalter mit .NET MVC 3 Razor EditorFür Erweiterungen?

Gibt es eine Möglichkeit, den HTML5-Platzhalter mit @ Html.EditorFor zu schreiben, oder sollte ich nur die TextBoxFor-Erweiterung verwenden, dh

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

Oder wäre es sinnvoll, eine eigene benutzerdefinierte Erweiterung zu schreiben, die möglicherweise das Anzeigeattribut ‘Beschreibung’ über DataAnnotations (ähnlich) verwendet?

Das gilt natürlich auch für den “Autofokus”.

Sie können sich den folgenden Artikel zum Schreiben eines benutzerdefinierten DataAnnotationsModelMetadataProvider .

Und hier ist ein weiterer, mehr ASP.NET MVC 3ish Weg mit der neu eingeführten IMetadataAware- Schnittstelle fortzufahren .

Beginnen Sie mit dem Erstellen eines benutzerdefinierten Attributs, das diese Schnittstelle implementiert:

 public class PlaceHolderAttribute : Attribute, IMetadataAware { private readonly string _placeholder; public PlaceHolderAttribute(string placeholder) { _placeholder = placeholder; } public void OnMetadataCreated(ModelMetadata metadata) { metadata.AdditionalValues["placeholder"] = _placeholder; } } 

Und dann dekoriere dein Modell damit:

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

Als nächstes definieren Sie einen Controller:

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

Eine entsprechende Sichtweise:

 @model MyViewModel @using (Html.BeginForm()) { @Html.EditorFor(x => x.Title)  } 

Und schließlich die Editor-Vorlage ( ~/Views/Shared/EditorTemplates/string.cshtml ):

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

Wie in der Antwort von Darin Dimitrov erwähnt, existiert die Prompt für genau diesen Zweck, so dass es nicht notwendig ist, ein benutzerdefiniertes Attribut zu erstellen . Aus der Dokumentation:

Ruft einen Wert ab, der zum Festlegen des Wasserzeichens für Eingabeaufforderungen auf der Benutzeroberfläche verwendet wird, oder legt diesen fest.

Um es zu verwenden, dekoriere einfach die Eigenschaft deines Ansichtsmodells wie folgt:

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

Dieser Text wird dann bequem in ModelMetadata.Watermark platziert. Standardmäßig ignoriert die Standardvorlage in MVC 3 die Eigenschaft Watermark , aber es funktioniert wirklich einfach. Alles, was Sie tun müssen, ist die Standard-String-Vorlage zu optimieren, um MVC mitzuteilen, wie es gerendert wird. Bearbeiten Sie einfach String.cshtml, wie dies bei Darin der Fall ist, außer dass Sie das Wasserzeichen von ModelMetadata.AdditionalValues , anstatt es direkt aus ModelMetadata.Watermark :

~ / Ansichten / Freigegeben / EditorTemplates / String.cshtml:

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

Und das ist alles.

Wie Sie sehen, ist der Schlüssel, um alles zum placeholder = ViewData.ModelMetadata.Watermark Bit placeholder = ViewData.ModelMetadata.Watermark .

Wenn Sie auch die Wasserzeichen für mehrzeilige Textfelder (Textareas) aktivieren möchten, machen Sie dasselbe für MultilineText.cshtml:

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

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

Ich bevorzuge es tatsächlich, den Anzeigenamen für den Platzhaltertext die meiste Zeit zu verwenden. Hier ist ein Beispiel für die Verwendung des DisplayName:

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

Ich habe eine so einfache class geschrieben:

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

Die Verwendung als solche:

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

Und Eigentum in einem Viewmodel:

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

Hinweis Aufforderungsparameter. In diesem Fall verwende ich Zeichenfolgen aus Ressourcen für die Lokalisierung, aber Sie können nur Zeichenfolgen verwenden, vermeiden Sie einfach den Parameter ResourceType.

Ich benutze diesen Weg mit Resource Datei (brauche keine Eingabe mehr!)

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

Hier ist eine Lösung, die ich mit den oben genannten Ideen gemacht habe, die für TextBoxFor und PasswordFor verwendet werden können:

 public static class HtmlHelperEx { public static MvcHtmlString TextBoxWithPlaceholderFor(this HtmlHelper htmlHelper, Expression> expression, object htmlAttributes) { var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); return htmlHelper.TextBoxFor(expression, htmlAttributes.AddAttribute("placeholder", metadata.Watermark)); } public static MvcHtmlString PasswordWithPlaceholderFor(this HtmlHelper htmlHelper, Expression> 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 AddAttribute(this object htmlAttributes, string name, object value) { var dictionary = htmlAttributes == null ? new Dictionary() : htmlAttributes.ToDictionary(); if (!String.IsNullOrWhiteSpace(name) && value != null && !String.IsNullOrWhiteSpace(value.ToString())) dictionary.Add(name, value); return dictionary; } public static IDictionary ToDictionary(this object obj) { return TypeDescriptor.GetProperties(obj) .Cast() .ToDictionary(property => property.Name, property => property.GetValue(obj)); } }