Proprietà EditorFor () e html


113

Le build di anteprima di Asp.Net MVC 2.0 forniscono helper come

Html.EditorFor(c => c.propertyname)

Se il nome della proprietà è stringa, il codice precedente restituisce un texbox.

Cosa succede se voglio passare le proprietà MaxLength e Size alla casella di testo o alla mia proprietà della classe CSS?

Devo creare un modello per ogni combinazione di taglia e lunghezza nella mia applicazione? In tal caso, ciò non rende utilizzabili i modelli predefiniti.

Risposte:


92

In MVC3, puoi impostare la larghezza come segue:

@Html.TextBoxFor(c => c.PropertyName, new { style = "width: 500px;" })

62
@vondip. Assicurati che sia un TEXTBOX e non un EDITOR. Doenst lavora con l'editor.
Kasper Skov

1
Funziona anche con textareas: @ Html.TextAreaFor (c => c.PropertyName, new {style = "width: 500px;"})
Tarzan

Si noti che alcune annotazioni di dati non sono supportati dalla TextBoxFor, che avrebbe lavorato con EditorFor, come ad esempio FormatString
AaronLS

14
Questa risposta non ignora totalmente di cosa si tratta, vale a dire la funzionalità EditorFor-Template?
Philipp M

1
L'uso di TextBoxFor tuttavia disattiva i formati di visualizzazione impostati come annotazioni di dati
Anders Lindén

61

Ho risolto questo problema creando un EditorTemplate denominato String.ascx nella mia cartella / Views / Shared / EditorTemplates:

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

A mio avviso, io uso

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

Funziona come un fascino per me!


1
brillante: avevo un menu a discesa DateTime di DatePicker che avevo già modellato, ma passare attributi extra ad esso si è rivelato doloroso - questo ha risolto per me, grazie!
Terry_Brown

EditorFor con maxlength non funziona per me (TextBoxFor sull'altro funziona)
Drejc

@tjeerdhans, ho usato questo codice per personalizzare il mio css. Funziona ma sfortunatamente sostituisce i valori CSS originali. Come posso farlo aggiungere al css originale invece?
Rosdi Kasim

33

Nessuna delle risposte in questo o in qualsiasi altro thread sull'impostazione degli attributi HTML per @ Html.EditorFor mi è stata di grande aiuto. Tuttavia, ho trovato un'ottima risposta su

Disegnare un helper @ Html.EditorFor

Ho usato lo stesso approccio e ha funzionato magnificamente senza scrivere molto codice extra. Notare che l'attributo id dell'output html di Html.EditorFor è impostato. Il codice di visualizzazione

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

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

La proprietà del modello con annotazione dei dati e formattazione della data come "gg MMM aaaa"

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

Ha funzionato come un fascino senza scrivere un sacco di codice extra. Questa risposta usa ASP.NET MVC 3 Razor C #.


1
Ha funzionato molto bene anche per me in MVC4.
atconway

1
La formattazione ha funzionato ma ora viene restituito null per i dati disabilitando efficacemente la casella.
Joe

2
Non so cosa sia con le persone MVC, è come se nessuno avesse scritto un sito Web che funziona con più lingue e formati per i numeri.
adudley

Molto bene. Questo è semplice, funziona e in realtà risponde alla domanda dell'OP, invece di fornire alternative. Utilizzando MVC4.
draconis

Avviso: DateTimes sembra essere visualizzato come type = "datetime", che è sbagliato per una data di nascita, e alcuni browser (come Firefox mobile) in realtà supportano correttamente quel tipo di input, incluso un componente temporale che probabilmente non supererà la convalida ed è difficile o impossibile per l'utente rimuovere.
brianary

25

Potrebbe voler guardare il post sul blog di Kiran Chand , utilizza metadati personalizzati sul modello di visualizzazione come:

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

Questo è combinato con modelli personalizzati che fanno uso dei metadati. Un approccio pulito e semplice secondo me, ma mi piacerebbe vedere questo caso d'uso comune integrato in mvc.


71
Stai scherzando? Questo è troppo eccessivo per una cosa così semplice. Torno sempre di più all'HTML puro e dimentico i metodi di aiuto gonfiati MVC. 5 minuti fa avevo un semplice TextboxFor che ha lanciato con successo un datepicker jquery. Ora, solo perché volevo cambiare il modo in cui formatta il valore della data precaricato in, ho dovuto cambiarlo in un EditorFor. Ma ora improvvisamente non posso più specificare i miei attributi HTML senza scrivere questi metodi di estensione personalizzati e helper eccessivamente gonfiati. Che scherzo. Deve esserci un modo più semplice, voi professori pazzi non sapete quando fermarvi.
Aaron

1
Penso che tu stia confondendo i contesti. Come puoi avere due diverse chiamate EditorFor con ognuna che ottiene i propri valori di dimensione e maxlength con il collegamento fornito? Se non vuoi usare EditorFor, puoi sempre usare TextBox helper o semplice html. Ma non è questo il problema!
chandmk

@Aaron a partire dall'ultimo MVC, puoi specificare attributi html aggiuntivi EditorForpassandoli come:new { htmlAttributes: { @class = "yourclass" } }
JoeBrockhaus

17

Sono sorpreso che nessuno abbia menzionato di passarlo in "additionalViewData" e di leggerlo dall'altra parte.

Visualizza (con interruzioni di riga, per chiarezza):

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

Modello dell'editor:

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

<%= Html.TextBox("", Model, ViewData["htmlAttributes"])) %>

Basandosi su questo ho creato un aiutante che prende in considerazione la fusione di attributi - stackoverflow.com/a/11498094/79842
Colin Bowern

6

Il problema è che il tuo modello può contenere diversi elementi HTML, quindi MVC non saprà a quale applicare la tua taglia / classe. Dovrai definirlo da solo.

Fai derivare il tuo modello dalla tua classe chiamata TextBoxViewModel:

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
  }

}

Nel modello puoi fare questo:

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

Dal tuo punto di vista fai:

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

Il primo modulo renderà il modello predefinito per la stringa. Il secondo modulo eseguirà il rendering del modello personalizzato.

La sintassi alternativa utilizza un'interfaccia fluida:

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

Si noti che invece di farlo nella vista, è possibile farlo anche nel controller, o molto meglio nel ViewModel:

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

Si noti inoltre che è possibile creare una classe TemplateViewModel di base, un terreno comune per tutti i modelli di visualizzazione, che conterrà il supporto di base per gli attributi / ecc.

Ma in generale penso che MVC v2 abbia bisogno di una soluzione migliore. È ancora beta: chiedi di farlo ;-)


Penso che un modo migliore per affrontare questo problema sia come ho menzionato qui stackoverflow.com/questions/1647609/… ... In breve, fare qualcosa di simile al modo in cui WPF gestisce il problema ... Elementi di stili arbitrari (in questo caso attributi) vengono passati al modello e il modello decide a quale elemento interno applicare lo stile ...
vdhant

6

Penso che usare i CSS sia la strada da percorrere. Vorrei poter fare di più con la codifica .NET, come in XAML, ma nel browser CSS è il re.

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


Funziona molto bene per apportare modifiche CSS specifiche al controllo quando si utilizza il EditorFormodello. Sto usando MVC4 e ha funzionato benissimo.
atconway

6

Come in MVC 5, se desideri aggiungere degli attributi puoi semplicemente farlo

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

Informazioni trovate da questo blog


3

Puoi definire attributi per le tue proprietà.

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

Questo è noto come System.ComponentModel.DataAnnotations. Se non riesci a trovare ValidationAttributeciò di cui hai bisogno, puoi sempre definire attributi personalizzati.

I migliori saluti, Carlos


3
Parla di attributi HTML come maxlength non validazione.
Mathias F

Mi auguro il motore vista sarebbe obbedire alle DataAnnotations anche. Non ho ancora scherzato con MVC2.
mxmissile

Ho provato l'annotazione dei dati StringLength. Non ha funzionato con EditorFor.
wayne.blackmon

3

Questa potrebbe non essere la soluzione più intelligente, ma è semplice. È possibile scrivere un'estensione per la classe HtmlHelper.EditorFor. In quell'estensione, puoi fornire un parametro di opzioni che scriverà le opzioni in ViewData per l'helper. Ecco un po 'di codice:

Innanzitutto, il metodo di estensione:

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

Successivamente, l'oggetto opzioni:

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

E infine, ecco la riga dal modello String.ascx:

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

Francamente, penso che questo sia semplice e chiaro per la povera anima che deve mantenere il tuo codice lungo la strada. Ed è facile estendere per vari altri bit di informazioni che desideri passare ai tuoi modelli. Finora sta funzionando bene per me in un progetto in cui sto cercando di racchiudere il più possibile in un set di modelli per aiutare a standardizzare l'html circostante, come http://bradwilson.typepad.com/blog/2009/ 10 / aspnet-mvc-2-templates-part-5-master-page-templates.html .


3

Ho scritto un post sul blog per rispondere alla mia domanda

Aggiunta del supporto degli attributi html per i modelli - ASP.Net MVC 2.0 Beta


L'idea di inserire proprietà di formattazione HTML nel modello (visualizzazione) è contraria all'idea di MVC di separare vista e logica! E se il modello avesse bisogno di diverse rappresentazioni in HTML?
saintedlama

2
@Saintedlama: Va benissimo mettere le annotazioni dei dati sul viewmodel , perché l'unico scopo di viewmodel è fornire un modello di dati strutturato per la vista . Da non confondere con il modello , che nella terminologia MVC di solito rappresenta un'entità DB, che non dovrebbe avere proprietà relative alla visualizzazione. Detto questo, è un peccato che le sue annotazioni viewmodel inizino con HTMLxxx perché ciò implica HTML come livello di presentazione, ma una linea deve essere tracciata da qualche parte. :) Inoltre, se riutilizza il viewmodel per esempio app silverlight, può facilmente aggiungere attributi SL al suo viewmodel.
Boris B.

3

Non so perché non funziona per Html.EditorFor ma ho provato TextBoxFor e ha funzionato per me.

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

... e anche la convalida funziona.


hai bisogno@class = "className"
JoeBrockhaus

2

Nella mia pratica ho scoperto che è meglio usare EditorTemplates con un solo HtmlHelper in esso - TextBox che è nella maggior parte dei casi. Se voglio un modello per una struttura html più complessa, scriverò un HtmlHelper separato.

Dato che possiamo attaccare l'intero oggetto ViewData al posto di htmlAttributes del TextBox. Inoltre possiamo scrivere del codice di personalizzazione per alcune proprietà del ViewData se necessitano di un trattamento speciale:

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

Di seguito sono riportati gli esempi della sintassi nella vista e l'html emesso:

@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">

2

Perché la domanda è per EditorFor non TextBoxFor Il suggerimento di WEFX non funziona.

Per modificare singole caselle di input, è possibile elaborare l'output del metodo EditorFor:

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

È anche possibile modificare TUTTI i tuoi EditorFors poiché risulta che MVC imposta la classe delle caselle di testo EditorFor con .text-box , quindi puoi semplicemente sovrascrivere questo stile, nel tuo foglio di stile o sulla pagina.

.text-box {
    width: 80em;
}

Inoltre, puoi impostare lo stile per

input[type="text"] {
    width: 200px;
}
  • questo sovrascrive .text-box e cambierà tutte le caselle di testo di input, EditorFor o altro.

Non tutte le caselle di testo EditorFor () sono di tipo input = "text". Le proprietà DateTime sembrano essere visualizzate come type = "datetime".
brianary

2

Ho anche avuto problemi con l'impostazione della larghezza di TextBox in MVC3, mentre l'impostazione dell'attributo Clsss funzionava per il controllo TextArea ma non per il controllo TextBoxFor o EditorFor:

Ho provato a seguire e ha funzionato per me:

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

anche in questo caso le Validazioni funzionano perfettamente.


2

Un modo per aggirare il problema è avere delegati sul modello di visualizzazione per gestire la stampa di rendering speciali come questo. L'ho fatto per una classe di paging, espongo una proprietà pubblica sul modello Func<int, string> RenderUrlper gestirla.

Quindi definisci come verrà scritto il bit personalizzato:

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

Visualizza la visualizzazione per la Pagingclasse:

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

... e per la Pagingvisualizzazione effettiva :

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

Potrebbe essere visto come un problema troppo complicato, ma io uso questi cercapersone ovunque e non sopporto di vedere lo stesso codice standard per renderli.


1

AGGIORNAMENTO: hm, ovviamente questo non funzionerà perché il modello viene passato per valore quindi gli attributi non vengono preservati; ma lascio questa risposta come un'idea.

Un'altra soluzione, penso, sarebbe quella di aggiungere i tuoi helper TextBox / etc, che verificheranno i tuoi attributi sul modello.

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

Questo è più facile ma non così conveniente / flessibile.



0

Mi è piaciuta molto la risposta di @tjeerdans che utilizza l'EditorTemplate denominato String.ascx nella cartella / Views / Shared / EditorTemplates. Sembra essere la risposta più diretta a questa domanda. Tuttavia, volevo un modello che usasse la sintassi Razor. Inoltre, sembra che MVC3 utilizzi il modello String come predefinito (vedere la domanda StackOverflow "il modello di visualizzazione mvc per le stringhe viene utilizzato per i numeri interi ") quindi è necessario impostare il modello su oggetto anziché su stringa. Il mio modello sembra funzionare finora:

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

0

L'ho risolto !!
Per Razor la sintassi è:
@Html.TextAreaFor(m=>m.Address, new { style="Width:174px" })questo regola la larghezza dell'area di testo alla larghezza che ho definito nel parametro di stile.
Per ASPx la sintassi è:
<%=Html.TextAreaFor(m => m.Description, new { cols = "20", rows = "15", style="Width:174px" })%>
questo farà il trucco

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.