Властивості EditorFor () та html


113

Asp.Net MVC 2.0 збірки попереднього перегляду надають таких помічників

Html.EditorFor(c => c.propertyname)

Якщо ім'я властивості є рядковим, наведений вище код надає текстове поле.

Що робити, якщо я хочу передати властивості MaxLength і Size у текстове поле чи власне властивість класу css?

Чи потрібно мені створити один шаблон для кожної комбінації розмірів і довжин у моїй програмі? Якщо так, це не робить шаблони за замовчуванням корисними.

Відповіді:


92

У MVC3 ви можете встановити ширину наступним чином:

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

62
@vondip. Переконайтеся, що це TEXTBOX, а не РЕДАКТОР. Найбільше працювати з редактором.
Каспер Сков

1
Він також працює з textareas: @ Html.TextAreaFor (c => c.PropertyName, новий {style = "width: 500px;"})
Тарзан

Зауважте, що деякі анотації даних не підтримуються TextBoxFor, який би працював з EditorFor, наприклад FormatString
AaronLS

14
Чи не відповідає ця відповідь, повністю ігноруйте питання, про яке йдеться, а саме функцію EditorFor-Template?
Philipp M

1
Однак, використовуючи TextBoxFor, вимикає формати відображення, які задаються як анотації даних
Anders Lindén

61

Я вирішив це, створивши EditorTemplate на ім'я String.ascx у папці / 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 }) %>

На мій погляд, я використовую

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

Діє як шарм для мене!


1
блискучий - У мене був випадок DateTime DateTime, який я вже шаблонував, але передавання йому додаткових атрибутів виявилося болісним - це вирішило це для мене, дякую!
Terry_Brown

EditorFor з maxlength не працює для мене (TextBoxFor з іншого робить)
Drejc

@tjeerdhans, я використовував цей код, щоб налаштувати свій css. Він працює, але, на жаль, замінює вихідні значення css. Як я можу зробити так, щоб він додав до оригінального css замість цього?
Росді Касім

33

Жодна відповідь у цій чи будь-якій іншій темі щодо встановлення HTML-атрибутів для @ Html.EditorДо мене не дуже допомогла. Однак я знайшов чудову відповідь на

Створення помічника @ Html.EditorДля помічника

Я використовував той самий підхід, і він спрацював прекрасно, не записуючи багато зайвого коду. Зауважте, що атрибут id виводу html виводу Html.EditorFor встановлений. Код перегляду

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

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

Властивість моделі з анотацією даних та форматуванням дати "dd MMM yyyy"

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

Працював як шарм, не написавши багато зайвого коду. У цій відповіді використовується ASP.NET MVC 3 Brzor C #.


1
Працював дуже добре і для мене в MVC4.
atconway

1
Форматування працювало, але тепер повертається нуль для даних, що фактично вимикають поле.
Джо

2
Я не знаю, що це з людьми MVC, це як би ніхто не написав веб-сайт, який працює з декількома мовами та форматами для чисел.
adudley

Дуже добре. Це просто, це працює, і він фактично відповідає на питання ОП, замість того, щоб надавати альтернативи. Використання MVC4.
draconis

Попередження: DateTimes відображається як type = "datetime", що неправильно для дати народження, а деякі веб-переглядачі (як Firefox mobile) насправді правильно підтримують цей тип введення, включаючи часовий компонент, який, ймовірно, не пройде перевірку і є складним або неможливо видалити користувача.
бріанарі

25

Можливо, захочеться переглянути блог Кірана Чанда , він використовує власні метадані у моделі перегляду, такі як:

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

Це поєднується з користувацькими шаблонами, які використовують метадані. На мій погляд, чистий і простий підхід, але я хотів би бачити, щоб цей звичайний випадок використання був вбудований у mvc.


71
Ви жартуєте? Це занадто багато зайвого для такої простої речі. Все більше і більше я повертаюсь до чистого HTML і забуваю про допоміжні методи MVC. 5 хвилин тому у мене з'явився простий TextboxДля якого успішно запустився вибірка дати jquery. Тепер тільки тому, що я хотів змінити, як він форматує попередньо завантажене значення дати, мені довелося змінити його на EditorFor. Але тепер раптом я більше не можу вказати свої власні атрибути HTML, не писати ці надмірно роздуті спеціальні методи розширення та помічники. Який жарт. Має бути простіший спосіб, ви скажені професори не знаєте, коли зупинитись.
Аарон

1
Я думаю, ви змішуєте контексти. Як ви можете мати два різні виклики редактора для кожного з них, отримуючи власний розмір та значення максимальної довжини за допомогою наданого вами посилання? Якщо ви не хочете використовувати EditorFor, ви завжди можете скористатися помічником TextBox або простим html. Але це не питання!
chandmk

@Aaron станом на останньому MVC, ви можете вказати додаткові атрибути html EditorFor, передавши його як:new { htmlAttributes: { @class = "yourclass" } }
JoeBrockhaus

17

Я здивований, що ніхто не згадав про те, щоб передати його в "AdditionalViewData" і прочитати його з іншого боку.

Перегляд (з розривами рядків, для наочності):

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

Шаблон редактора:

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

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

Грунтуючись на цьому , я створив помічник , який бере до уваги об'єднання атрибутів - stackoverflow.com/a/11498094/79842
Colin Bowern

6

Проблема полягає в тому, що ваш шаблон може містити кілька елементів HTML, тому MVC не знатиме, до якого застосувати розмір / клас. Вам доведеться визначити це самостійно.

Зробіть свій шаблон похідним із власного класу під назвою 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
  }

}

У шаблоні ви можете це зробити:

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

На ваш погляд, ви робите:

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

Перша форма відобразить шаблон за замовчуванням для рядка. У другій формі буде відображено спеціальний шаблон.

Альтернативний синтаксис використовує вільний інтерфейс:

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

Зауважте, що замість того, щоб робити це у представленні даних, ви також можете це зробити в контролері або набагато краще в 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) });
}

Також зауважте, що ви можете створити базовий клас TemplateViewModel - спільну основу для всіх ваших шаблонів перегляду - який буде містити базову підтримку атрибутів / тощо.

Але загалом я думаю, що MVC v2 потребує кращого рішення. Це все-таки бета-версія - іди проси;


Я вважаю, що кращим способом вирішення цього питання є те, як я згадував тут stackoverflow.com/questions/1647609/… ... Коротше кажучи, щось подібне до того, як WPF вирішує проблему ... Довільні елементи стилів (в даному випадку атрибути) передаються до шаблону, і шаблон вирішує, до якого внутрішнього елемента він буде застосовувати стиль до ...
vdhant

6

Я думаю, що використання CSS - це шлях. Я хотів би, щоб я міг зробити більше з кодування .NET, як у XAML, але в браузері CSS є королем.

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>

Джо


Це дуже добре працює для внесення змін, що стосуються CSS, при використанні EditorForшаблону. Я використовую MVC4, і це спрацювало чудово.
atconway

6

Як і в MVC 5, якщо ви хочете додати будь-які атрибути, ви можете просто зробити

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

Інформація, знайдена в цьому блозі


3

Ви можете визначити атрибути для своїх властивостей.

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

Це відомо як System.ComponentModel.DataAnnotations. Якщо ви не можете знайтиValidationAttribute що вам потрібно, ви завжди можете визначити власні атрибути.

З найкращими побажаннями, Карлос


3
Він говорить про Html-атрибути, такі як maxlength not validation.
Матіас F

Я сподіваюся, що механізм перегляду також буде підкорятися DataAnnotations. Я ще не заплутався з MVC2.
mxmissle

Я спробував анотацію даних StringLength. Це не працювало з EditorFor.
wayne.blackmon

3

Це може бути не найкрутішим рішенням, але це прямо. Ви можете написати розширення до класу HtmlHelper.EditorFor. У цьому розширенні ви можете надати параметр параметрів, який запише параметри в ViewData для помічника. Ось код:

Спочатку метод розширення:

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

Далі об’єкт параметрів:

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

І нарешті, ось рядок із шаблону String.ascx:

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

Відверто кажучи, я думаю, що це ясно і зрозуміло бідній душі, яка має підтримувати ваш код у дорозі. І це легко розширити на різні інші шматочки інформації, які ви хочете передати вашим шаблонам. Наразі це добре працює для мене в проекті, де я намагаюся загорнути якомога більше у набір шаблонів, щоб допомогти стандартизувати навколишній HTML, a la http://bradwilson.typepad.com/blog/2009/ 10 / aspnet-mvc-2-templates-part-5-master-page-templates.html .


3

Я написав запис у блозі, щоб відповісти на власне запитання

Додавання підтримки атрибутів html для шаблонів - ASP.Net MVC 2.0 Beta


Ідея розміщення властивостей форматування HTML у моделі (view) суперечить ідеї MVC для розділення перегляду та логіки! Що робити, якщо модель потребує різних представлень у HTML?
saintslama

2
@Saintedlama: Цілком чудово розміщувати анотації даних у viewmodel , оскільки єдиною метою viewmodel є створення структурованої моделі даних для перегляду . Не плутати з моделлю , яка в термінології MVC зазвичай являє собою об'єкт БД, який не повинен мати ніяких властивостей, пов'язаних із переглядом. Сказавши це, прикро, що його анотації viewmodel починаються з HTMLxxx, оскільки це передбачає HTML як шар презентації, але лінію потрібно десь намалювати. :) Крім того, якщо він повторно використовувати програму viewmodel для програми Silverlight, він може легко додати атрибути SL до своєї viewmodel.
Борис Б.

3

Я не знаю, чому це не працює для Html.EditorFor, але я спробував TextBoxFor, і він працював на мене.

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

... а також працює перевірка.


вам потрібно@class = "className"
JoeBrockhaus

2

У своїй практиці я виявив, що найкраще використовувати EditorTemplates із лише одним HtmlHelper у ньому - TextBox, який є в більшості випадків. Якщо я хочу шаблон для більш складної структури html, я напишу окремий HtmlHelper.

Враховуючи, що ми можемо вставити весь об’єкт ViewData замість htmlAttributes TextBox. Крім того, ми можемо написати код налаштування для деяких властивостей ViewData, якщо вони потребують спеціального лікування:

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

Нижче наведено приклади синтаксису у представленні та вихідний 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">

2

Оскільки питання стосується EditorFor не TextBoxFor, пропозиція WEFX не працює.

Для зміни окремих вхідних полів ви можете обробити вихід методу EditorFor:

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

Можна також змінити ВСІ ваш редактор, оскільки виявляється, MVC встановлює клас текстових полів редактора для .text-box , тому ви можете просто перекрити цей стиль у вашому аркуші стилів або на сторінці.

.text-box {
    width: 80em;
}

Крім того, ви можете встановити стиль для

input[type="text"] {
    width: 200px;
}
  • це перекриває .text-box і змінить усі текстові поля вводу, EditorFor або іншим чином.

Не всі текстові поля EditorFor () є вхідним типом = "текст". Властивості DateTime, схоже, відображаються як type = "datetime".
бріанарі

2

У мене також виникли проблеми із встановленням ширини TextBox у MVC3, при встановленні атрибута Clsss працював для управління TextArea, але не для управління TextBoxДля управління EditorFor:

Я спробував наступне, і це працювало для мене:

@ Html.TextBoxFor (model => model.Title, новий {Class = "textBox", style = "width: 90%;"})

також у цьому випадку перевірки працюють чудово.


2

Один із способів ви можете його обійти, маючи делегатів на переглянутій моделі для обробки друку спеціального візуалізації, як цього. Я зробив це для класового підключення, я виставляю публічну власність на модельFunc<int, string> RenderUrl щоб вирішити це.

Отже, визначте, як буде записаний спеціальний біт:

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

Виведіть подання для Pagingкласу:

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

... і для фактичного Pagingперегляду:

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

Це може сприйматись як надмірно складні питання, але я використовую ці пейджери скрізь і не можу витримати бачення того ж кодового коду, щоб отримати їх.


1

ОНОВЛЕННЯ: hm, очевидно, це не буде працювати, оскільки модель передається за значенням, тому атрибути не збереглися; але цю відповідь я залишаю як ідею.

Іншим рішенням, я думаю, було б додати власні помічники TextBox / etc, які перевірять ваші власні атрибути на моделі.

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

Це легше, але не настільки зручно / гнучко.


1

Це найчистіший і найелегантніший / простий спосіб отримати рішення тут.

Блискуча публікація в блозі та безладна надмірність у написанні спеціальних методів розширення / помічників, як шалений професор.

http://geekswithblogs.net/michelotti/archive/2010/02/05/mvc-2-editor-template-with-datetime.aspx


0

Мені дуже сподобалась відповідь @tjeerdans, яка використовує редактор шаблону з назвою String.ascx у папці / Views / Shared / EditorTemplates. Здається, це найпростіша відповідь на це питання. Однак я хотів шаблон із використанням синтаксису Razor. Крім того, здається, що MVC3 використовує шаблон String як за замовчуванням (див. Питання StackOverflow " Шаблон відображення mvc для рядків використовується для цілих чисел "), тому вам потрібно встановити модель на об'єкт, а не на рядок. Здається, мій шаблон працює дотепер:

@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

Я це вирішив !!
Для синтаксису Razor синтаксис такий:
@Html.TextAreaFor(m=>m.Address, new { style="Width:174px" })це регулює ширину області тексту до ширини, яку я визначив у параметрі стилю.
Для ASPx синтаксис такий:
<%=Html.TextAreaFor(m => m.Description, new { cols = "20", rows = "15", style="Width:174px" })%>
це зробить трюк

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.