EditorFor () - und HTML-Eigenschaften

113

Asp.Net MVC 2.0 Preview Builds bieten Hilfen wie

Html.EditorFor(c => c.propertyname)

Wenn der Eigenschaftsname string ist, wird mit dem obigen Code eine Texbox gerendert.

Was ist, wenn ich die Eigenschaften MaxLength und Size an das Textfeld oder meine eigene CSS-Klasseneigenschaft übergeben möchte?

Muss ich für jede Größen- und Längenkombination in meiner Anwendung eine Vorlage erstellen? Wenn ja, werden die Standardvorlagen dadurch nicht verwendet.

chandmk
quelle

Antworten:

92

In MVC3 können Sie die Breite wie folgt einstellen:

@Html.TextBoxFor(c => c.PropertyName, new { style = "width: 500px;" })
WEFX
quelle
62
@ Vondip. Stellen Sie sicher, dass es sich um eine TEXTBOX und nicht um einen EDITOR handelt. Arbeite nicht mit dem Editor.
Kasper Skov
1
Es funktioniert auch mit Textbereichen: @ Html.TextAreaFor (c => c.PropertyName, new {style = "width: 500px;"})
Tarzan
Beachten Sie, dass einige Datenanmerkungen von der TextBoxFor nicht unterstützt werden, was mit EditorFor funktionieren würde, z. B. FormatString
AaronLS
14
Ignoriert diese Antwort nicht völlig, worum es bei der Frage geht, nämlich um die EditorFor-Template-Funktionalität?
Philipp M
1
Mit TextBoxFor werden jedoch Anzeigeformate deaktiviert, die als Datenanmerkungen festgelegt sind
Anders Lindén,
61

Ich habe dieses Problem gelöst, indem ich eine EditorTemplate mit dem Namen String.ascx in meinem Ordner / Views / Shared / EditorTemplates erstellt habe:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<string>" %>
<% int size = 10;
   int maxLength = 100;
   if (ViewData["size"] != null)
   {
       size = (int)ViewData["size"];
   }
   if (ViewData["maxLength"] != null)
   {
       maxLength = (int)ViewData["maxLength"];
   }
%>
<%= Html.TextBox("", Model, new { Size=size, MaxLength=maxLength }) %>

Aus meiner Sicht benutze ich

<%= Html.EditorFor(model => model.SomeStringToBeEdited, new { size = 15, maxLength = 10 }) %>

Funktioniert wie ein Zauber für mich!

tjeerdhans
quelle
1
Genial - Ich hatte ein DateTicker-Dropdown-Menü "DateTime", das ich bereits als Vorlage verwendet hatte, aber das Übergeben zusätzlicher Attribute erwies sich als schmerzhaft - dies löste es für mich, danke!
Terry_Brown
EditorFor mit maximaler Länge funktioniert nicht für mich (TextBoxFor auf der anderen Seite funktioniert)
Drejc
@tjeerdhans, ich habe diesen Code verwendet, um mein CSS anzupassen. Es funktioniert, ersetzt aber leider die ursprünglichen CSS-Werte. Wie kann ich es stattdessen an das ursprüngliche CSS anhängen lassen ?
Rosdi Kasim
33

Keine der Antworten in diesem oder einem anderen Thread zum Festlegen von HTML-Attributen für @ Html.EditorFor hat mir sehr geholfen. Allerdings habe ich bei eine gute Antwort gefunden

Styling eines @ Html.EditorFor-Helfers

Ich habe den gleichen Ansatz verwendet und es hat wunderbar funktioniert, ohne viel zusätzlichen Code zu schreiben. Beachten Sie, dass das ID-Attribut der HTML-Ausgabe von Html.EditorFor festgelegt ist. Der Ansichtscode

<style type="text/css">
#dob
{
   width:6em;
}
</style>

@using (Html.BeginForm())
{
   Enter date: 
   @Html.EditorFor(m => m.DateOfBirth, null, "dob", null)
}

Die Modelleigenschaft mit Datenanmerkung und Datumsformatierung als "TT MMM JJJJ"

[Required(ErrorMessage= "Date of birth is required")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd MMM yyyy}")]
public DateTime DateOfBirth { get; set; }

Arbeitete wie ein Zauber, ohne viel zusätzlichen Code zu schreiben. Diese Antwort verwendet ASP.NET MVC 3 Razor C #.

wayne.blackmon
quelle
1
Hat auch in MVC4 sehr gut funktioniert.
Atconway
1
Die Formatierung hat funktioniert, aber jetzt wird null für die Daten zurückgegeben, wodurch die Box effektiv deaktiviert wird.
Joe
2
Ich weiß nicht, was es mit MVC-Leuten ist, es ist, als hätte niemand eine Website geschrieben, die mit mehreren Sprachen und Formaten für Zahlen funktioniert.
Adudley
Sehr gut. Dies ist einfach, funktioniert und beantwortet tatsächlich die Frage des OP, anstatt Alternativen bereitzustellen. Verwenden von MVC4.
Draconis
Warnung: DateTimes scheinen als type = "datetime" zu rendern, was für ein Geburtsdatum falsch ist, und einige Browser (wie Firefox Mobile) unterstützen diesen Eingabetyp tatsächlich korrekt, einschließlich einer Zeitkomponente, die die Validierung wahrscheinlich nicht besteht und schwierig oder schwierig ist für den Benutzer nicht zu entfernen.
Brian
25

Vielleicht möchten Sie sich Kiran Chands Blog-Beitrag ansehen. Er verwendet benutzerdefinierte Metadaten für das Ansichtsmodell wie:

[HtmlProperties(Size = 5, MaxLength = 10)]
public string Title { get; set; }

Dies wird mit benutzerdefinierten Vorlagen kombiniert, die die Metadaten verwenden. Meiner Meinung nach ein sauberer und einfacher Ansatz, aber ich würde mir wünschen, dass dieser allgemeine Anwendungsfall in mvc integriert ist.

tj.
quelle
71
Machst du Witze? Das ist viel zu viel Overkill für so eine einfache Sache. Immer mehr kehre ich zu reinem HTML zurück und vergesse die aufgeblähten MVC-Hilfsmethoden. Vor 5 Minuten hatte ich eine einfache TextboxFor, die erfolgreich einen jquery datepicker startete. Nur weil ich ändern wollte, wie der vorinstallierte Datumswert formatiert wird, musste ich ihn in einen EditorFor ändern. Aber jetzt kann ich plötzlich keine eigenen HTML-Attribute mehr angeben, ohne diese übermäßig aufgeblähten benutzerdefinierten Erweiterungsmethoden und Helfer zu schreiben. Was für ein Witz. Es muss einen einfacheren Weg geben, Sie verrückten Professoren wissen nicht, wann sie aufhören sollen.
Aaron
1
Ich denke, Sie verwechseln Kontexte. Wie können Sie zwei verschiedene EditorFor-Aufrufe haben, wobei jeder mit dem von Ihnen angegebenen Link seine eigene Größe und maximale Länge erhält? Wenn Sie EditorFor nicht verwenden möchten, können Sie immer den TextBox-Helfer oder einfaches HTML verwenden. Das ist aber nicht die Frage!
Chandmk
@ Aaron ab dem neuesten MVC können Sie zusätzliche HTML-Attribute mit angeben, EditorForindem Sie es übergeben als:new { htmlAttributes: { @class = "yourclass" } }
JoeBrockhaus
17

Ich bin überrascht, dass niemand erwähnt hat, dass er es in "AdditionalViewData" weitergegeben und auf der anderen Seite gelesen hat.

Ansicht (aus Gründen der Übersichtlichkeit mit Zeilenumbrüchen):

<%= Html.EditorFor(c => c.propertyname, new
    {
        htmlAttributes = new
        {
            @class = "myClass"
        }
    }
)%>

Editor-Vorlage:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<string>" %>

<%= Html.TextBox("", Model, ViewData["htmlAttributes"])) %>
Ishmael Smyrnow
quelle
Darauf aufbauend habe ich einen Helfer erstellt, der das Zusammenführen von Attributen berücksichtigt - stackoverflow.com/a/11498094/79842
Colin Bowern
6

Das Problem ist, dass Ihre Vorlage mehrere HTML-Elemente enthalten kann, sodass MVC nicht weiß, auf welches Ihre Größe / Klasse angewendet werden soll. Sie müssen es selbst definieren.

Lassen Sie Ihre Vorlage von Ihrer eigenen Klasse namens TextBoxViewModel ableiten:

public class TextBoxViewModel
{
  public string Value { get; set; }
  IDictionary<string, object> moreAttributes;
  public TextBoxViewModel(string value, IDictionary<string, object> moreAttributes)
  {
    // set class properties here
  }
  public string GetAttributesString()
  {
     return string.Join(" ", moreAttributes.Select(x => x.Key + "='" + x.Value + "'").ToArray()); // don't forget to encode
  }

}}

In der Vorlage können Sie dies tun:

<input value="<%= Model.Value %>" <%= Model.GetAttributesString() %> />

Aus Ihrer Sicht tun Sie:

<%= Html.EditorFor(x => x.StringValue) %>
or
<%= Html.EditorFor(x => new TextBoxViewModel(x.StringValue, new IDictionary<string, object> { {'class', 'myclass'}, {'size', 15}}) %>

Das erste Formular rendert die Standardvorlage für die Zeichenfolge. Das zweite Formular rendert die benutzerdefinierte Vorlage.

Alternative Syntax verwenden fließende Schnittstelle:

public class TextBoxViewModel
{
  public string Value { get; set; }
  IDictionary<string, object> moreAttributes;
  public TextBoxViewModel(string value, IDictionary<string, object> moreAttributes)
  {
    // set class properties here
    moreAttributes = new Dictionary<string, object>();
  }

  public TextBoxViewModel Attr(string name, object value)
  {
     moreAttributes[name] = value;
     return this;
  }

}}

   // and in the view
   <%= Html.EditorFor(x => new TextBoxViewModel(x.StringValue).Attr("class", "myclass").Attr("size", 15) %>

Beachten Sie, dass Sie dies nicht in der Ansicht, sondern auch im Controller oder viel besser im ViewModel tun können:

public ActionResult Action()
{
  // now you can Html.EditorFor(x => x.StringValue) and it will pick attributes
  return View(new { StringValue = new TextBoxViewModel(x.StringValue).Attr("class", "myclass").Attr("size", 15) });
}

Beachten Sie auch, dass Sie die Basis-TemplateViewModel-Klasse erstellen können - eine gemeinsame Grundlage für alle Ihre Ansichtsvorlagen -, die grundlegende Unterstützung für Attribute / etc. Enthält.

Aber im Allgemeinen denke ich, dass MVC v2 eine bessere Lösung braucht. Es ist immer noch Beta - frag danach ;-)

Königin3
quelle
Ich denke, eine bessere Möglichkeit, damit umzugehen, ist, wie ich hier erwähnt habe. Stackoverflow.com/questions/1647609/… ... Kurz gesagt, etwas Ähnliches tun, wie WPF das Problem behandelt ... Beliebige Stilelemente (in diesem Fall aktiviert) Attribute) werden an die Vorlage übergeben und die Vorlage entscheidet, auf welches interne Element der Stil
angewendet wird
6

Ich denke, CSS ist der richtige Weg. Ich wünschte, ich könnte mehr mit .NET-Codierung tun, wie in XAML, aber im Browser ist CSS König.

Site.css

#account-note-input { 
  width:1000px; 
  height:100px; 
} 

.cshtml

<div class="editor-label"> 
  @Html.LabelFor(model => model.Note) 
</div> 
<div class="editor-field"> 
  @Html.EditorFor(model => model.Note, null, "account-note-input", null) 
  @Html.ValidationMessageFor(model => model.Note) 
</div>

Joe

Joe Kahl
quelle
Dies funktioniert sehr gut, um steuerungsspezifische CSS-Änderungen bei Verwendung der EditorForVorlage vorzunehmen . Ich benutze MVC4 und das hat super funktioniert.
Atconway
6

Wenn Sie wie bei MVC 5 Attribute hinzufügen möchten, können Sie dies einfach tun

 @Html.EditorFor(m => m.Name, new { htmlAttributes = new { @required = "true", @anotherAttribute = "whatever" } })

Informationen aus diesem Blog gefunden

Jay
quelle
3

Sie können Attribute für Ihre Eigenschaften definieren.

[StringLength(100)]
public string Body { get; set; }

Dies ist bekannt als System.ComponentModel.DataAnnotations. Wenn Sie das benötigte nicht finden ValidationAttribute, können Sie immer benutzerdefinierte Attribute definieren.

Beste Grüße, Carlos

Carlos Fernandes
quelle
3
Er spricht über HTML-Attribute wie maximale Länge, nicht Validierung.
Mathias F
Ich würde hoffen, dass die View Engine auch den DataAnnotations gehorcht. Ich habe noch nicht mit MVC2 herumgespielt.
mxmissile
Ich habe die StringLength-Datenanmerkung ausprobiert. Mit EditorFor hat es nicht funktioniert.
Wayne.blackmon
3

Dies ist möglicherweise nicht die beste Lösung, aber es ist unkompliziert. Sie können eine Erweiterung für die Klasse HtmlHelper.EditorFor schreiben. In dieser Erweiterung können Sie einen Optionsparameter angeben, der die Optionen für den Helfer in die ViewData schreibt. Hier ist ein Code:

Zunächst die Erweiterungsmethode:

public static MvcHtmlString EditorFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, TemplateOptions options)
{
    return helper.EditorFor(expression, options.TemplateName, new
    {
        cssClass = options.CssClass
    });
}

Als nächstes das Optionsobjekt:

public class TemplateOptions
{
    public string TemplateName { get; set; }
    public string CssClass { get; set; }
    // other properties for info you'd like to pass to your templates,
    // and by using an options object, you avoid method overload bloat.
}

Und zum Schluss noch die Zeile aus der String.ascx-Vorlage:

<%= Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = ViewData["cssClass"] ?? "" }) %>

Ehrlich gesagt denke ich, dass dies für die arme Seele, die Ihren Code später beibehalten muss, unkompliziert und klar ist. Und es ist einfach, verschiedene andere Informationen zu erweitern, die Sie an Ihre Vorlagen weitergeben möchten. Bisher funktioniert es gut für mich in einem Projekt, in dem ich versuche, so viel wie möglich in eine Reihe von Vorlagen zu packen, um die Standardisierung des umgebenden HTML-Codes zu unterstützen, a la http://bradwilson.typepad.com/blog/2009/ 10 / aspnet-mvc-2-templates-part-5-master-page-templates.html .

Stelle
quelle
3

Ich habe einen Blogeintrag geschrieben, um meine eigene Frage zu beantworten

Unterstützung für HTML-Attribute für Vorlagen hinzufügen - ASP.Net MVC 2.0 Beta

chandmk
quelle
Die Idee, HTML-Formatierungseigenschaften in das (Ansichts-) Modell einzufügen, widerspricht der Idee von MVC, Ansicht und Logik zu trennen! Was wäre, wenn das Modell unterschiedliche Darstellungen in HTML benötigen würde?
Saintlama
2
@Saintedlama: Es ist vollkommen in Ordnung , Datenanmerkungen in das Ansichtsmodell einzufügen , da der einzige Zweck des Ansichtsmodells darin besteht, ein strukturiertes Datenmodell für die Ansicht bereitzustellen . Nicht zu verwechseln mit dem Modell , das in der MVC-Terminologie normalerweise eine DB-Entität darstellt, die keine ansichtsbezogenen Eigenschaften haben sollte. Trotzdem ist es bedauerlich, dass seine Viewmodel-Annotationen mit HTMLxxx beginnen, da dies HTML als Präsentationsebene impliziert, aber irgendwo eine Linie gezogen werden muss. :) Außerdem kann er, wenn er das Ansichtsmodell beispielsweise für die Silverlight-App wiederverwendet, seinem Ansichtsmodell problemlos SL-Attribute hinzufügen.
Boris B.
3

Ich weiß nicht, warum es für Html.EditorFor nicht funktioniert, aber ich habe TextBoxFor ausprobiert und es hat für mich funktioniert.

@Html.TextBoxFor(m => m.Name, new { Class = "className", Size = "40"})

... und auch die Validierung funktioniert.

Piotr Czyż
quelle
Sie brauchen@class = "className"
JoeBrockhaus
2

In meiner Praxis habe ich festgestellt, dass es am besten ist, EditorTemplates mit nur einem HtmlHelper zu verwenden - TextBox, das in den meisten Fällen der Fall ist. Wenn ich eine Vorlage für eine komplexere HTML-Struktur möchte, schreibe ich einen separaten HTML-Helfer.

Vorausgesetzt, wir können das gesamte ViewData-Objekt anstelle von htmlAttributes der TextBox verwenden. Darüber hinaus können wir Anpassungscode für einige der Eigenschaften der ViewData schreiben, wenn sie einer besonderen Behandlung bedürfen:

@model DateTime?
@*
    1) applies class datepicker to the input;
    2) applies additionalViewData object to the attributes of the input
    3) applies property "format" to the format of the input date.
*@
@{
    if (ViewData["class"] != null) { ViewData["class"] += " datepicker"; }
    else { ViewData["class"] = " datepicker"; }
    string format = "MM/dd/yyyy";
    if (ViewData["format"] != null)
    {
        format = ViewData["format"].ToString();
        ViewData.Remove("format");
    }
}

@Html.TextBox("", (Model.HasValue ? Model.Value.ToString(format) : string.Empty), ViewData)

Unten finden Sie Beispiele für die Syntax in der Ansicht und das ausgegebene HTML:

@Html.EditorFor(m => m.Date)
<input class="datepicker" data-val="true" data-val-required="&amp;#39;Date&amp;#39; must not be empty." id="Date" name="Date" type="text" value="01/08/2012">
@Html.EditorFor(m => m.Date, new { @class = "myClass", @format = "M/dd" })
<input class="myClass datepicker" data-val="true" data-val-required="&amp;#39;Date&amp;#39; must not be empty." id="Date" name="Date" type="text" value="1/08">
Dmitry Efimenko
quelle
2

Da die Frage für EditorFor nicht TextBoxFor WEFX ist, funktioniert der Vorschlag nicht.

Zum Ändern einzelner Eingabefelder können Sie die Ausgabe der EditorFor-Methode verarbeiten:

<%: new HtmlString(Html.EditorFor(m=>m.propertyname).ToString().Replace("class=\"text-box single-line\"", "class=\"text-box single-line my500pxWideClass\"")) %>

Es ist auch möglich, ALLE Ihre EditorFors zu ändern, da MVC die Klasse der EditorFor-Textfelder mit .text-box festlegt . Daher können Sie diesen Stil einfach in Ihrem Stylesheet oder auf der Seite überschreiben.

.text-box {
    width: 80em;
}

Außerdem können Sie den Stil für festlegen

input[type="text"] {
    width: 200px;
}
  • Dies überschreibt das Textfeld und ändert alle Eingabetextfelder, EditorFor oder andere.
stuartdotnet
quelle
Nicht alle EditorFor () -Textfelder sind vom Eingabetyp = "Text". DateTime-Eigenschaften scheinen als type = "datetime" zu rendern.
Brian
2

Ich hatte auch Probleme beim Festlegen der Breite von TextBox in MVC3, während das Festlegen des Clsss-Attributs für das TextArea-Steuerelement, jedoch nicht für das TextBoxFor-Steuerelement oder das EditorFor-Steuerelement funktionierte:

Ich habe versucht zu folgen und das hat bei mir funktioniert:

@ Html.TextBoxFor (model => model.Title, new {Class = "textBox", style = "width: 90%;"})

auch in diesem Fall funktionieren Validierungen einwandfrei.

Ashish
quelle
2

Eine Möglichkeit, dies zu umgehen, besteht darin, Delegierte im Ansichtsmodell zu haben, die das Ausdrucken eines solchen speziellen Renderings übernehmen. Ich habe dies für eine Paging-Klasse getan und eine öffentliche Eigenschaft für das Modell verfügbar gemachtFunc<int, string> RenderUrl damit umzugehen.

Definieren Sie also, wie das benutzerdefinierte Bit geschrieben wird:

Model.Paging.RenderUrl = (page) => { return string.Concat(@"/foo/", page); };

Geben Sie die Ansicht für die PagingKlasse aus:

@Html.DisplayFor(m => m.Paging)

... und für die aktuelle PagingAnsicht:

@model Paging
@if (Model.Pages > 1)
{
    <ul class="paging">
    @for (int page = 1; page <= Model.Pages; page++)
    {
        <li><a href="@Model.RenderUrl(page)">@page</a></li>
    }
    </ul>
}

Es könnte als übermäßig kompliziert angesehen werden, aber ich benutze diese Pager überall und konnte es nicht ertragen, denselben Code für das Boilerplate zu sehen, um sie zu rendern.

Phil Cooper
quelle
1

UPDATE: hm, das funktioniert natürlich nicht, da das Modell als Wert übergeben wird und die Attribute nicht erhalten bleiben. aber ich lasse diese Antwort als Idee.

Ich denke, eine andere Lösung wäre, Ihre eigenen TextBox / etc-Helfer hinzuzufügen, die nach Ihren eigenen Attributen im Modell suchen.

public class ViewModel
{
  [MyAddAttribute("class", "myclass")]
  public string StringValue { get; set; }
}

public class MyExtensions
{
  public static IDictionary<string, object> GetMyAttributes(object model)
  {
     // kind of prototype code...
     return model.GetType().GetCustomAttributes(typeof(MyAddAttribute)).OfType<MyAddAttribute>().ToDictionary(
          x => x.Name, x => x.Value);
  }
}

<!-- in the template -->
<%= Html.TextBox("Name", Model, MyExtensions.GetMyAttributes(Model)) %>

Dieser ist einfacher, aber nicht so praktisch / flexibel.

Königin3
quelle
0

Die Antwort von @tjeerdans, bei der die EditorTemplate mit dem Namen String.ascx im Ordner / Views / Shared / EditorTemplates verwendet wird, hat mir sehr gut gefallen. Es scheint die direkteste Antwort auf diese Frage zu sein. Ich wollte jedoch eine Vorlage mit Razor-Syntax. Darüber hinaus scheint MVC3 die Zeichenfolgenvorlage als Standard zu verwenden (siehe die StackOverflow-Frage " MVC-Anzeigevorlage für Zeichenfolgen wird für Ganzzahlen verwendet "), sodass Sie das Modell auf Objekt anstatt auf Zeichenfolge festlegen müssen. Meine Vorlage scheint bisher zu funktionieren:

@model object 

@{  int size = 10; int maxLength = 100; }

@if (ViewData["size"] != null) {
    Int32.TryParse((string)ViewData["size"], out size); 
} 

@if (ViewData["maxLength"] != null) {
    Int32.TryParse((string)ViewData["maxLength"], out maxLength); 
}

@Html.TextBox("", Model, new { Size = size, MaxLength = maxLength})
zielot
quelle
0

Ich habe es gelöst !!
Für Razor lautet die Syntax:
@Html.TextAreaFor(m=>m.Address, new { style="Width:174px" })Hiermit wird die Breite des Textbereichs an die Breite angepasst, die ich im Stilparameter definiert habe.
Für ASPx lautet die Syntax:
<%=Html.TextAreaFor(m => m.Description, new { cols = "20", rows = "15", style="Width:174px" })%>
Dies reicht aus

Sorangwala Abbasali
quelle