EditorFor()和html属性

时间:2009-10-26 14:57:39

标签: c# asp.net-mvc asp.net-mvc-2

Asp.Net MVC 2.0预览版提供了诸如

之类的帮助
Html.EditorFor(c => c.propertyname)

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

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

我是否需要在我的应用程序中为每种大小和长度组合创建一个模板?如果是这样,那就不会使默认模板可用。

20 个答案:

答案 0 :(得分:91)

在MVC3中,您可以按如下方式设置宽度:

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

答案 1 :(得分: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 }) %>

对我来说就像一个魅力!

答案 2 :(得分:33)

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

找到了一个很好的答案

Styling an @Html.EditorFor helper

我使用相同的方法,并且它工作得很漂亮而无需编写大量额外的代码。请注意,设置了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#。

答案 3 :(得分:25)

可能希望查看Kiran Chand's Blog post,他在视图模型上使用自定义元数据,例如:

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

这与使用元数据的自定义模板相结合。在我看来,这是一个干净简单的方法,但我希望看到mvc内置的这个常见用例。

答案 4 :(得分: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"])) %>

答案 5 :(得分: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需要更好的解决方案。它仍然是Beta - 请求它; - )

答案 6 :(得分:6)

与MVC 5一样,如果您想添加任何属性,只需执行

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

this blog

找到的信息

答案 7 :(得分: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>

答案 8 :(得分:3)

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

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

......还有验证工作。

答案 9 :(得分:3)

我写了一篇博客文章来回答我自己的问题

Adding html attributes support for Templates - ASP.Net MVC 2.0 Beta

答案 10 :(得分: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,la http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-5-master-page-templates.html

答案 11 :(得分:3)

您可以定义属性的属性。

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

这称为System.ComponentModel.DataAnnotations。 如果找不到所需的ValidationAttribute,则可以始终定义自定义属性。

最诚挚的问候, 卡洛斯

答案 12 :(得分: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">

答案 13 :(得分: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或其他。

答案 14 :(得分:2)

我还遇到了在MVC3中设置TextBox宽度的问题,而设置Clsss属性适用于TextArea控件但不适用于TextBoxFor控件或EditorFor控件:

我试过以下&amp;这对我有用:

 @ Html.TextBoxFor(model =&gt; model.Title,new {Class =“textBox”,style =“width:90%;”})

在这种情况下,验证工作也很完美。

答案 15 :(得分: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>
}

它可能被视为过于复杂的问题,但我在任何地方都使用这些寻呼机,并且无法看到相同的样板代码来渲染它们。

答案 16 :(得分:1)

这是获得解决方案的最简洁,最优雅/最简单的方式。

精彩的博客文章并没有像编写疯狂教授一样编写自定义扩展/辅助方法的杂乱。

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

答案 17 :(得分:1)

UPDATE:嗯,显然这不起作用,因为模型是按值传递的,所以不保留属性;但我把这个答案留作了一个主意。

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

这个更容易,但不那么方便/灵活。

答案 18 :(得分:0)

我真的很喜欢@tjeerdans的答案,该答案利用了/ Views / Shared / EditorTemplates文件夹中名为String.ascx的EditorTemplate。这似乎是这个问题最直接的答案。但是,我想要一个使用Razor语法的模板。此外,似乎MVC3使用String模板作为默认值(请参阅StackOverflow问题“mvc display template for strings is used for integers”),因此您需要将模型设置为object而不是string。到目前为止,我的模板似乎正在运作:

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

答案 19 :(得分: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" })%>
这将做到这一点