Asp.Net MVC 2.0 预览版本提供了像
Html.EditorFor(c => c.propertyname)
如果属性名称是字符串,上面的代码会渲染一个 texbox。
如果我想将 MaxLength 和 Size 属性传递给文本框或我自己的 css 类属性怎么办?
我是否需要为我的应用程序中的每种尺寸和长度组合创建一个模板?如果是这样,那不会使默认模板可用。
Asp.Net MVC 2.0 预览版本提供了像
Html.EditorFor(c => c.propertyname)
如果属性名称是字符串,上面的代码会渲染一个 texbox。
如果我想将 MaxLength 和 Size 属性传递给文本框或我自己的 css 类属性怎么办?
我是否需要为我的应用程序中的每种尺寸和长度组合创建一个模板?如果是这样,那不会使默认模板可用。
在 MVC3 中,您可以按如下方式设置宽度:
@Html.TextBoxFor(c => c.PropertyName, new { style = "width: 500px;" })
我通过在我的 /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 }) %>
对我来说就像一个魅力!
这个或任何其他线程中关于为@Html.EditorFor 设置HTML 属性的答案都没有对我有很大帮助。但是,我确实找到了一个很好的答案
我使用了相同的方法,并且无需编写大量额外代码就可以很好地工作。请注意,设置了 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#。
可能想看看Kiran Chand 的博客文章,他在视图模型上使用自定义元数据,例如:
[HtmlProperties(Size = 5, MaxLength = 10)]
public string Title { get; set; }
这与使用元数据的自定义模板相结合。我认为这是一种干净简单的方法,但我希望看到这个常见的用例内置于 mvc 中。
I'm surprised no one mentioned passing it in "additionalViewData" and reading it on the other side.
View (with line breaks, for clarity):
<%= Html.EditorFor(c => c.propertyname, new
{
htmlAttributes = new
{
@class = "myClass"
}
}
)%>
Editor template:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<string>" %>
<%= Html.TextBox("", Model, ViewData["htmlAttributes"])) %>
问题是,您的模板可以包含多个 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 - 去请求它;-)
I think using CSS is the way to go. I wish I could do more with .NET coding, like in XAML, but in the browser CSS is king.
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
在 MVC 5 中,如果你想添加任何属性,你可以简单地做
@Html.EditorFor(m => m.Name, new { htmlAttributes = new { @required = "true", @anotherAttribute = "whatever" } })
我不知道为什么它对 Html.EditorFor 不起作用,但我尝试了 TextBoxFor 并且它对我有用。
@Html.TextBoxFor(m => m.Name, new { Class = "className", Size = "40"})
...以及验证工作。
这可能不是最巧妙的解决方案,但它很简单。您可以为 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,例如http://bradwilson.typepad.com/blog/2009/ 10/aspnet-mvc-2-templates-part-5-master-page-templates.html。
您可以为您的属性定义属性。
[StringLength(100)]
public string Body { get; set; }
这被称为System.ComponentModel.DataAnnotations
. 如果你找不到ValidationAttribute
你需要的,你总是可以定义自定义属性。
最好的问候,卡洛斯
I wrote a blog entry to answer my own question
Adding html attributes support for Templates - ASP.Net MVC 2.0 Beta
我在 MVC3 中设置 TextBox 的宽度时也遇到了问题,而设置 Clsss 属性适用于 TextArea 控件,但不适用于 TextBoxFor 控件或 EditorFor 控件:
我尝试了以下对我有用的方法:
@Html.TextBoxFor(model => model.Title, new { Class = "textBox", style = "width:90%;" })
在这种情况下,验证也可以正常工作。
因为问题是针对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;
}
你可以绕过它的一种方法是让视图模型上的委托来处理打印出这样的特殊渲染。我已经为分页类完成了此操作,我在模型上公开了一个公共属性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>
}
这可能被视为过于复杂的事情,但我在任何地方都使用这些寻呼机,并且无法忍受看到相同的样板代码来渲染它们。
在我的实践中,我发现最好使用只有一个 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="&#39;Date&#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="&#39;Date&#39; must not be empty." id="Date" name="Date" type="text" value="1/08">
这是在这里获得解决方案的最干净、最优雅/最简单的方法。
精彩的博客文章,在编写自定义扩展/帮助方法时不会像疯了教授那样乱七八糟。
http://geekswithblogs.net/michelotti/archive/2010/02/05/mvc-2-editor-template-with-datetime.aspx
更新:嗯,显然这不起作用,因为模型是按值传递的,因此不保留属性;但我把这个答案作为一个想法。
我认为另一种解决方案是添加您自己的 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)) %>
这一个更容易,但不那么方便/灵活。
我真的很喜欢@tjeerdans 的答案,它利用 /Views/Shared/EditorTemplates 文件夹中名为 String.ascx 的 EditorTemplate。这似乎是对这个问题的最直接的答案。但是,我想要一个使用 Razor 语法的模板。此外,似乎 MVC3 使用 String 模板作为默认值(参见 StackOverflow 问题“ mvc display template for strings is used for integers ”),因此您需要将模型设置为对象而不是字符串。到目前为止,我的模板似乎正在工作:
@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})
我解决了!!
对于 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" })%>
这样就可以了