EditorFor()和html属性


113

Asp.Net MVC 2.0预览版提供了类似的帮助

Html.EditorFor(c => c.propertyname)

如果属性名称为字符串,则上面的代码将呈现一个texbox。

如果我想将MaxLength和Size属性传递给文本框或我自己的CSS类属性怎么办?

我需要为我的应用程序中的每种尺寸和长度组合创建一个模板吗?如果是这样,则不会使默认模板可用。

Answers:


92

在MVC3中,可以如下设置宽度:

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

62
@vondip。确保其是TEXTBOX,而不是EDITOR。Doenst与编辑一起工作。
卡斯珀·斯科夫

1
它还适用于textareas:@ Html.TextAreaFor(c => c.PropertyName,new {style =“ width:500px;”})
Tarzan

请注意,TextBoxFor不支持某些数据注释,这些注释可与EditorFor一起使用,例如FormatString
AaronLS 2012年

14
这个答案是否完全忽略了问题所在,即EditorFor-Template功能?
菲利普·M

1
然而使用TextBoxFor断开被设定为数据的注释的显示格式
的Anders椴

61

我通过在/ Views / Shared / EditorTemplates文件夹中创建一个名为String.ascx的EditorTemplate来解决此问题:

<%@ 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
精采-我有一个已经选择模板的datepicker DateTime下拉菜单,但是事实证明它很痛苦-这为我解决了,谢谢!
Terry_Brown

具有maxlength的EditorFor不适用于我(其他情况下适用于
TextBoxFor

@tjeerdhans,我使用此代码来自定义CSS。它可以工作,但不幸的是它代替了原始的css值。我如何使其附加到原始CSS?
Rosdi Kasim 2013年

33

在这个或任何其他线程中,为@ Html.EditorFor设置HTML属性没有答案对我有太大帮助。但是,我的确找到了一个很好的答案

设置@ Html.Editor样式

我使用了相同的方法,并且在无需编写大量额外代码的情况下,效果很好。请注意,设置了Html.EditorFor的html输出的id属性。查看代码

<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 Razor C#。


1
在MVC4中,对我来说也非常有效。
atconway 2012年

1
格式化有效,但现在返回的null为有效禁用该框的数据。
2012年

2
我不知道MVC的人是什么人,就像没有人写过一个使用多种语言和数字格式的网站一样。
adudley 2012年

很好。这很简单,有效,并且实际上回答了OP的问题,而不是提供替代方案。使用MVC4。
draconis 2014年

警告:DateTimes似乎呈现为type =“ datetime”,这对于生日而言是错误的,并且某些浏览器(例如Firefox mobile)实际上正确地支持该输入类型,包括可能无法通过验证并且很难或无法通过的时间组件。用户无法删除。
2015年

25

可能想看一下Kiran Chand的Blog帖子,他在视图模型上使用了自定义元数据,例如:

[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 2011年

@Aaron自最新的MVC起,您可以EditorFor通过传递以下内容来指定其他html属性:new { htmlAttributes: { @class = "yourclass" } }
JoeBrockhaus 2014年

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
科林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类-所有视图模板的共同点-包含对attribute / etc的基本支持。

但总的来说,我认为MVC v2需要更好的解决方案。它仍然是Beta-要求它;-)


我认为一种更好的处理方式是我在这里提到的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>


当使用EditorFor模板时,这对于进行控件特定的CSS更改非常有效。我正在使用MVC4,效果很好。
atconway 2012年

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而不是验证)。
Mathias F

希望视图引擎也遵守DataAnnotations。我还没弄懂MVC2。
mxmissile

我尝试了StringLength数据注释。它不适用于EditorFor。
wayne.blackmon '02

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 Beta


将HTML格式设置属性放在(视图)模型上的想法与MVC分离视图和逻辑的想法相反!如果模型需要HTML中的不同表示形式怎么办?
saintedlama

2
@Saintedlama:最好在viewmodel上放置数据注释,因为viewmodel的唯一目的是为view提供结构化的数据模型。不要与model混淆,在MVC术语中,该model通常代表一个DB实体,该实体不应具有任何与视图相关的属性。话虽这么说,不幸的是,他的视图模型注释以HTMLxxx开头,因为这暗示了HTML作为表示层,但是必须在某处画一条线。:)此外,如果他为Silverlight应用程序重用视图模型,则可以轻松地将SL属性添加到他的视图模型中。
鲍里斯·B

3

我不知道为什么它不适用于Html.EditorFor,但我尝试了TextBoxFor,它对我有用。

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

...以及验证工作。


您需要@class = "className"
JoeBrockhaus 2014年

2

在我的实践中,我发现最好只使用一个带有HtmlHelper的EditorTemplates-在大多数情况下为TextBox。如果我想要一个用于更复杂的html结构的模板,我将编写一个单独的HtmlHelper。

鉴于我们可以将整个ViewData对象粘贴在TextBox的htmlAttributes处。此外,如果需要特殊处理,我们可以为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\"")) %>

事实证明,也可以更改所有EditorFors,因为MVC使用.text-box设置了EditorFor文本框的类,因此您可以在样式表或页面中覆盖此样式。

.text-box {
    width: 80em;
}

此外,您可以为

input[type="text"] {
    width: 200px;
}
  • 这将覆盖.text-box并将更改所有输入文本框,EditorFor或其他。

并非所有的EditorFor()文本框都输入type =“ text”。DateTime属性似乎呈现为type =“ datetime”。
2015年

2

我在设置MVC3中TextBox的宽度时也遇到了问题,而设置Clsss属性可用于TextArea控件,但不适用于TextBoxFor控件或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

更新:嗯,显然这是行不通的,因为模型是通过值传递的,因此不会保留属性。但我将这个答案留给了一个想法。

我认为,另一种解决方案是添加您自己的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)) %>

这比较容易,但不那么方便/灵活。



0

我真的很喜欢@tjeerdans答案,它使用了/ Views / Shared / EditorTemplates文件夹中名为String.ascx的EditorTemplate。这似乎是对这个问题最直接的答案。但是,我想要一个使用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" })将文本区域的宽度调整为我在style参数中定义的宽度。
对于ASPx,语法为:
<%=Html.TextAreaFor(m => m.Description, new { cols = "20", rows = "15", style="Width:174px" })%>
这可以解决问题

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.