EditorFor() and html properties

ASP.Net MVC 2.0预览版本提供了如下帮助

Html.EditorFor(c => c.propertyname)

如果属性名为 string,则上面的代码呈现一个文本框。

What if I want to pass in MaxLength and Size properties to the text box or my own css class property?

Do I need to create one template for each size and length combinations in my application? If so, that doesn't make the default templates that usable.

219933 次浏览

可以为属性定义属性。

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

这就是 System.ComponentModel.DataAnnotations。 如果你找不到你需要的 ValidationAttribute,你可以定义自定义属性。

最好的问候, 卡洛斯

问题是,您的模板可以包含多个 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 版——去要求它; -)

更新: 嗯,显然这不会起作用,因为模型是通过值传递的,所以属性不会被保留; 但是我把这个答案留作一个想法。

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

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

May want to look at Kiran Chand 的博客文章, he uses custom metadata on the view model such as:

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

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

这可能不是最圆滑的解决方案,但它是直截了当的。您可以编写 HtmlHelper 的扩展。课堂编辑。在该扩展中,您可以提供一个选项参数,用于将选项写入到帮助器的 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
});
}

接下来,options 对象:

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

我通过在我的/Views/Shared/EditorTemplate 文件夹中创建一个名为 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 }) %>

对我来说太有效了!

This is the cleanest and most elegant/simple way to get a solution here.

Brilliant blog post and no messy overkill in writing custom extension/helper methods like a mad professor.

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

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

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

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

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

...and also validation works.

我很惊讶没有人提到在“ addtionalViewData”中传递它并在另一端阅读它。

查看 (为了清楚起见,使用换行符) :

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

编辑模板:

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


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

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

假设我们可以将整个 ViewData 对象代替 TextBox 的 htmlAttritribute。此外,如果 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">

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

样式化@Html.EditorFor helper

我使用了相同的方法,它工作得很好,没有编写很多额外的代码。注意 Html 的 Html 输出的 id 属性。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”的 model 属性

[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 # 。

因为问题是对于 编辑而不是 TextBoxFor WEFX 的建议不起作用。

For changing individual input boxes, you can process the output of the EditorFor method:

<%: 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 {
width: 80em;
}

此外,您还可以为

input[type="text"] {
width: 200px;
}
  • 此命令重写. text-box,并将更改所有输入文本框、 EditorFor 或其他方式。

我非常喜欢@tjeerdan 的回答,它利用了/Views/Shared/EditorTemplate 文件夹中名为 String.ascx 的 EditorTemplate。这似乎是这个问题最直接的答案。但是,我需要一个使用 Razor 语法的模板。此外,MVC3似乎使用 String 模板作为默认值(参见 StackOverflow 问题“ 字符串的 mvc 显示模板用于整数”) ,因此您需要将模型设置为 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})

我认为应该使用 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>

Joe

在 MVC3中设置 TextBox 的宽度也有问题,而设置 Clsss 属性对 TextArea 控件有效,但对 TextBoxFor 控件或 EditorFor 控件无效:

我试着遵循下面的方法,这对我很有效:

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

在这种情况下,验证也是完美的。

解决这个问题的一个方法是在视图模型上设置委托,以处理如下所示的特殊呈现的打印。我已经为一个分页类做了这些,我在模型 Func<int, string> RenderUrl上公开了一个公共属性来处理它。

因此,定义如何编写自定义位:

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

输出 Paging类的视图:

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

...and for the actual Paging view:

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

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

在 MVC5中,如果您想添加任何属性,只需简单地这样做

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

这个博客找到的信息

我破案了!
对于 Razor 来说,语法是:
@Html.TextAreaFor(m=>m.Address, new { style="Width:174px" })将文本区域宽度调整为我在样式参数中定义的宽度。
对于 ASPx,语法是:
<%=Html.TextAreaFor(m => m.Description, new { cols = "20", rows = "15", style="Width:174px" })%>
这样就行了