【问题标题】:EditorFor() and html propertiesEditorFor() 和 html 属性
【发布时间】:2010-12-10 03:59:36
【问题描述】:

Asp.Net MVC 2.0 预览版提供了像

这样的助手
Html.EditorFor(c => c.propertyname)

如果属性名是字符串,上面的代码会渲染一个texbox。

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

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

【问题讨论】:

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


    【解决方案1】:

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

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

    【讨论】:

    • @vondip。确保它是 TEXTBOX 而不是 EDITOR。不使用编辑器。
    • 它也适用于文本区域:@Html.TextAreaFor(c => c.PropertyName, new { style = "width: 500px;" })
    • 请注意,TextBoxFor 不支持某些数据注释,它可以与 EditorFor 一起使用,例如 FormatString
    • 这不是答案,完全忽略了问题是什么,即EditorFor-Template功能吗?
    • 使用 TextBoxFor 会关闭设置为数据注释的显示格式
    【解决方案2】:

    我通过在我的 /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 }) %>
    

    对我来说就像一个魅力!

    【讨论】:

    • 太棒了 - 我有一个我已经模板化的日期选择器 DateTime 下拉菜单,但是将额外的属性传递给它被证明是痛苦的 - 这为我解决了,谢谢!
    • EditorFor with maxlength 对我不起作用(TextBoxFor 对我起作用)
    • @tjeerdhans,我使用这段代码来自定义我的 css。它可以工作,但不幸的是它替换原始的 css 值。如何将其 追加 到原始 css 中?
    【解决方案3】:

    这个或任何其他线程中关于为@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#。

    【讨论】:

    • 在 MVC4 中对我来说也非常好。
    • 格式有效,但现在为有效禁用框的数据返回 null。
    • 我不知道 MVC 人是怎么回事,好像没有人写过一个可以使用多种语言和数字格式的网站。
    • 非常好。这很简单,它有效,它实际上回答了 OP 的问题,而不是提供替代方案。使用 MVC4。
    • 警告:DateTimes 似乎呈现为 type="datetime",这对于出生日期是错误的,并且某些浏览器(如 Firefox 移动版)实际上正确支持该输入类型,包括可能赢得的时间组件'不通过验证,用户很难或不可能删除。
    【解决方案4】:

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

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

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

    【讨论】:

    • 你在开玩笑吗?对于这么简单的事情,这太过分了。我越来越多地回到纯 HTML 并忘记了 MVC 臃肿的辅助方法。 5 分钟前,我有一个简单的 TextboxFor,它成功启动了一个 jquery datepicker。现在只是因为我想更改它格式化预加载日期值的方式,我不得不将其更改为 EditorFor。但是现在突然之间,如果不编写这些过于臃肿的自定义扩展方法和帮助程序,我就不能再指定我自己的 HTML 属性了。真是笑话。必须有一个更简单的方法,你们这些疯狂的教授不知道什么时候该停下来。
    • 我认为您混淆了上下文。你怎么能有两个不同的 EditorFor 调用,每个调用都有自己的 size 和 maxlength 值,你提供的链接?如果您不想使用 EditorFor,您始终可以使用 TextBox 助手或简单的 html。但这不是问题!
    • @Aaron 在最新的 MVC 中,您可以使用 EditorFor 指定其他 html 属性,方法是将其传递为:new { htmlAttributes: { @class = "yourclass" } }
    【解决方案5】:

    我很惊讶没有人提到在“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"])) %>
    

    【讨论】:

    【解决方案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 - 去问问吧 ;-)

    【讨论】:

    • 我认为处理这个问题的更好方法是我在这里提到的stackoverflow.com/questions/1647609/…... 总之做一些类似于 WPF 处理问题的方式... 任意样式元素(在这种情况下的属性)被传递给模板,模板决定它将样式应用于哪个内部元素......
    【解决方案7】:

    我认为使用 CSS 是可行的方法。我希望我可以用 .NET 编码做更多事情,比如在 XAML 中,但在浏览器中 CSS 才是王道。

    网站.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,效果很好。
    【解决方案8】:

    在 MVC 5 中,如果你想添加任何属性,你可以简单地做

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

    this blog找到的信息

    【讨论】:

      【解决方案9】:

      您可以为您的属性定义属性。

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

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

      最好的问候, 卡洛斯

      【讨论】:

      • 他谈到了像 maxlength 这样的 HTML 属性而不是验证。
      • 希望视图引擎也会遵守 DataAnnotations。我还没有弄乱 MVC2。
      • 我尝试了 StringLength 数据注释。它不适用于 EditorFor。
      【解决方案10】:

      这可能不是最巧妙的解决方案,但它很简单。您可以为 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

      【讨论】:

        【解决方案11】:

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

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

        【讨论】:

        • 将 HTML 格式化属性放在(视图)模型上的想法是违反 MVC 分离视图和逻辑的想法!如果模型需要在 HTML 中使用不同的表示形式怎么办?
        • @Saintedlama:在 viewmodel 上放置数据注释非常好,因为 viewmodel 的唯一目的是为 view 提供结构化数据模型.不要与 model 混淆,在 MVC 术语中,它通常表示一个 DB 实体,它不应该有任何与视图相关的属性。话虽如此,不幸的是他的视图模型注释以 HTMLxxx 开头,因为这意味着 HTML 作为表示层,但必须在某处画一条线。 :) 此外,如果他将视图模型重用于silverlight 应用程序,他可以轻松地将 SL 属性添加到他的视图模型中。
        【解决方案12】:

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

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

        ...验证也有效。

        【讨论】:

        • 你需要@class = "className"
        【解决方案13】:

        在我的实践中,我发现最好使用只有一个 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">
        

        【讨论】:

          【解决方案14】:

          因为问题是针对 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() 文本框都是 input type="text"。 DateTime 属性似乎呈现为 type="datetime"。
          【解决方案15】:

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

          我尝试了以下对我有用的方法:

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

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

          【讨论】:

            【解决方案16】:

            您可以绕过它的一种方法是让视图模型上的委托来处理打印出这样的特殊渲染。我已经为分页类做了这个,我在模型Func&lt;int, string&gt; 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>
            }
            

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

            【讨论】:

              【解决方案17】:

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

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

                这是在这里获得解决方案的最干净、最优雅/最简单的方法。

                精彩的博文,在编写自定义扩展/辅助方法时不会像疯了教授那样乱七八糟。

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

                【讨论】:

                  【解决方案19】:

                  我真的很喜欢 @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})
                  

                  【讨论】:

                    【解决方案20】:

                    我解决了!!
                    对于 Razor,语法是:
                    @Html.TextAreaFor(m=&gt;m.Address, new { style="Width:174px" }) 这会将文本区域的宽度调整为我在样式参数中定义的宽度。
                    对于 ASPx,语法为:
                    &lt;%=Html.TextAreaFor(m =&gt; m.Description, new { cols = "20", rows = "15", style="Width:174px" })%&gt;
                    这样就可以了

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-04-13
                      • 1970-01-01
                      • 2023-03-26
                      • 1970-01-01
                      • 2014-07-26
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多