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, а не EDITOR. Работаю с редактором.
Kasper Skov

1
Он также работает с текстовыми полями: @ Html.TextAreaFor (c => c.PropertyName, new {style = "width: 500px;"})
Тарзан

Обратите внимание, что некоторые аннотации данных не поддерживаются TextBoxFor, который будет работать с EditorFor, например FormatString
AaronLS

14
Разве этот ответ не полностью игнорирует суть вопроса, а именно функциональность EditorFor-Template?
Philipp M

1
Однако использование TextBoxFor отключает форматы отображения, заданные как аннотации данных,
Андерс Линден,

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 datepicker, которое я уже создавал по шаблону, но передача ему дополнительных атрибутов оказалась болезненной - это решило проблему для меня, спасибо!
Terry_Brown

EditorFor с maxlength у меня не работает (TextBoxFor с другой стороны)
Drejc

@tjeerdhans, я использовал этот код для настройки своего css. Он работает, но, к сожалению, заменяет исходные значения css. Как я могу добавить его к исходному CSS?
Росди Касим

33

Ни один из ответов в этом или любом другом потоке по установке атрибутов HTML для @ Html.EditorFor мне не очень помог. Однако я нашел отличный ответ на

Стилизация помощника @ Html.EditorFor

Я использовал тот же подход, и он отлично работал без написания большого количества дополнительного кода. Обратите внимание, что атрибут 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)
}

Свойство модели с аннотацией данных и форматированием даты как «дд МММ гггг».

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

Работает как шарм, без написания лишнего кода. В этом ответе используется ASP.NET MVC 3 Razor C #.


1
У меня тоже хорошо работал в MVC4.
atconway,

1
Форматирование сработало, но теперь возвращается значение null для данных, эффективно отключающих поле.
Джо

2
Я не знаю, что это такое с людьми MVC, похоже, что никто не написал веб-сайт, который работает с несколькими языками и форматами чисел.
adudley 09

Очень хорошо. Это просто, это работает и фактически отвечает на вопрос OP, а не предоставляет альтернативы. Используя MVC4.
draconis

Предупреждение: DateTimes отображается как type = "datetime", что неверно для даты рождения, и некоторые браузеры (например, мобильный Firefox) действительно правильно поддерживают этот тип ввода, включая компонент времени, который, вероятно, не пройдет проверку и является сложным или невозможно удалить пользователем.
brianary

25

Возможно, вы захотите посмотреть сообщение в блоге Кирана Чанда , он использует настраиваемые метаданные в модели представления, такие как:

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

Это сочетается с настраиваемыми шаблонами, которые используют метаданные. На мой взгляд, это чистый и простой подход, но я бы хотел, чтобы этот типичный вариант использования был встроен в mvc.


71
Ты смеешься? Это слишком много для такой простой вещи. Я все больше и больше возвращаюсь к чистому HTML и забываю о раздутых вспомогательных методах MVC. 5 минут назад у меня был простой TextboxFor, который успешно запустил jquery datepicker. Теперь, только потому, что я хотел изменить способ форматирования предварительно загруженного значения даты, мне пришлось изменить его на EditorFor. Но теперь внезапно я больше не могу указывать свои собственные атрибуты HTML, не написав этих чрезмерно раздутых пользовательских методов расширения и помощников. Ну и шутка. Должен быть способ попроще, вы, безумные профессора, не знаете, когда остановиться.
Аарон

1
Я думаю, вы путаете контексты. Как у вас может быть два разных вызова EditorFor, каждый из которых получает свои собственные значения размера и максимальной длины с предоставленной вами ссылкой? Если вы не хотите использовать 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 - общую основу для всех ваших шаблонов представления - который будет содержать базовую поддержку атрибутов / etc.

Но в целом я думаю, что 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.
Mathias F

Я надеюсь, что движок представления также будет подчиняться DataAnnotations. Я еще не возился с MVC2.
mxmissile

Я попробовал аннотацию данных StringLength. С EditorFor это не сработало.
wayne.blackmon 01

3

Возможно, это не самое удачное решение, но оно простое. Вы можете написать расширение для класса HtmlHelper.EditorFor. В этом расширении вы можете указать параметр options, который будет записывать параметры в 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, а-ля http://bradwilson.typepad.com/blog/2009/ 10 / aspnet-mvc-2-templates-part-5-master-page-templates.html .


3

Я написал запись в блоге, чтобы ответить на свой вопрос

Добавление поддержки атрибутов html для шаблонов - бета-версия ASP.Net MVC 2.0


Идея помещения свойств форматирования HTML в модель (представления) противоречит идее MVC для разделения представления и логики! Что, если модели потребуются разные представления в HTML?
saintedlama 08

2
@Saintedlama: Совершенно нормально размещать аннотации данных в модели представления , потому что единственная цель модели представления - предоставить структурированную модель данных для представления . Не путать с моделью , которая в терминологии MVC обычно представляет собой объект БД, который не должен иметь никаких свойств, связанных с представлением. Сказав это, жаль, что его аннотации модели представления начинаются с HTMLxxx, потому что это подразумевает HTML как уровень представления, но где-то нужно провести линию. :) Кроме того, если он повторно использует модель просмотра, скажем, для приложения silverlight, он может легко добавить атрибуты SL в свою модель просмотра.
Борис Б.

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

Потому что вопрос к редактору для not TextBoxFor, предложение WEFX не работает.

Для изменения отдельных полей ввода вы можете обработать вывод метода EditorFor:

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

Также можно изменить ВСЕ ваши EditorFors, поскольку оказывается, что MVC устанавливает класс текстовых полей EditorFor с .text-box , поэтому вы можете просто переопределить этот стиль в своей таблице стилей или на странице.

.text-box {
    width: 80em;
}

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

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

Не все текстовые поля EditorFor () являются input type = "text". Свойства DateTime отображаются как type = "datetime".
brianary

2

У меня также была проблема с установкой ширины TextBox в MVC3, при этом установка атрибута Clsss работала для элемента управления TextArea, но не для элемента управления TextBoxFor или элемента EditorFor:

Я пробовал следовать, и это сработало для меня:

@ Html.TextBoxFor (model => model.Title, new {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

ОБНОВЛЕНИЕ: хм, очевидно, это не сработает, потому что модель передается по значению, поэтому атрибуты не сохраняются; но я оставляю этот ответ как идею.

Другим решением, я думаю, было бы добавление ваших собственных помощников 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, который использует EditorTemplate с именем 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.