Thuộc tính EditorFor () và html


113

Các bản dựng xem trước Asp.Net MVC 2.0 cung cấp cho những người trợ giúp như

Html.EditorFor(c => c.propertyname)

Nếu tên thuộc tính là chuỗi, đoạn mã trên sẽ hiển thị một hộp thư.

Điều gì sẽ xảy ra nếu tôi muốn chuyển các thuộc tính MaxLength và Size vào hộp văn bản hoặc thuộc tính lớp css của riêng tôi?

Tôi có cần tạo một mẫu cho từng kết hợp kích thước và chiều dài trong ứng dụng của mình không? Nếu vậy, điều đó không làm cho các mẫu mặc định có thể sử dụng được.

Câu trả lời:


92

Trong MVC3, bạn có thể đặt chiều rộng như sau:

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

62
@vondip. Đảm bảo rằng nó là TEXTBOX chứ không phải là EDITOR. Doenst làm việc với biên tập viên.
Kasper Skov

1
Nó cũng hoạt động với textareas: @ Html.TextAreaFor (c => c.PropertyName, new {style = "width: 500px;"})
Tarzan

Lưu ý rằng một số chú thích dữ liệu không được hỗ trợ bởi các TextBoxFor, mà sẽ làm việc với EditorFor, chẳng hạn như FormatString
AaronLS

14
Câu trả lời này không, hoàn toàn bỏ qua những gì câu hỏi về, cụ thể là chức năng EditorFor-Template?
Philipp M

1
Sử dụng TextBoxFor tuy nhiên tắt định dạng hiển thị được đặt làm chú thích dữ liệu
Anders Linden

61

Tôi đã giải quyết điều này bằng cách tạo một EditorTemplate có tên String.ascx trong thư mục / Views / Shared / EditorTemplates của tôi:

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

Theo quan điểm của tôi, tôi sử dụng

<%= Html.EditorFor(model => model.SomeStringToBeEdited, new { size = 15, maxLength = 10 }) %>

Hoạt động như một sự quyến rũ đối với tôi!


1
tuyệt vời - tôi đã có một trình chọn ngày DateTime thả xuống mà tôi đã tạo mẫu, nhưng việc chuyển các thuộc tính bổ sung cho nó thật khó chịu - điều này đã giải quyết cho tôi, cảm ơn!
Terry_Brown

EditorFor với maxlength không làm việc cho tôi (TextBoxFor mặt khác thực hiện)
Drejc

@tjeerdhans, tôi đã sử dụng mã này để tùy chỉnh css của mình. Nó hoạt động nhưng tiếc là nó thay thế các giá trị css ban đầu. Làm cách nào tôi có thể làm cho nó thêm vào css ban đầu?
Rosdi Kasim

33

Không có câu trả lời nào trong chuỗi này hoặc bất kỳ chuỗi nào khác về việc đặt thuộc tính HTML cho @ Html.EditorFor đã giúp tôi nhiều. Tuy nhiên, tôi đã tìm thấy một câu trả lời tuyệt vời tại

Tạo kiểu cho @ Html.EditorFor helper

Tôi đã sử dụng cách tiếp cận tương tự và nó hoạt động tuyệt vời mà không cần viết thêm nhiều mã. Lưu ý rằng thuộc tính id của đầu ra html của Html.EditorFor đã được đặt. Mã chế độ xem

<style type="text/css">
#dob
{
   width:6em;
}
</style>

@using (Html.BeginForm())
{
   Enter date: 
   @Html.EditorFor(m => m.DateOfBirth, null, "dob", null)
}

Thuộc tính mô hình với chú thích dữ liệu và định dạng ngày tháng là "dd MMM yyyy"

[Required(ErrorMessage= "Date of birth is required")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd MMM yyyy}")]
public DateTime DateOfBirth { get; set; }

Làm việc như một sự quyến rũ mà không cần viết nhiều mã bổ sung. Câu trả lời này sử dụng ASP.NET MVC 3 Razor C #.


1
Tôi cũng làm việc rất tốt trong MVC4.
atconway,

1
Định dạng đã hoạt động nhưng bây giờ null được trả về cho dữ liệu vô hiệu hóa hộp một cách hiệu quả.
Joe

2
Tôi không biết nó là gì với những người MVC, nó giống như không ai từng viết một trang web hoạt động với nhiều ngôn ngữ và định dạng cho các con số.
adudley

Rất tốt. Điều này đơn giản, nó hoạt động và nó thực sự trả lời câu hỏi của OP, thay vì cung cấp các lựa chọn thay thế. Sử dụng MVC4.
draconis

Cảnh báo: DateTimes dường như hiển thị dưới dạng type = "datetime", sai ngày sinh và một số trình duyệt (như Firefox dành cho thiết bị di động) thực sự hỗ trợ chính xác kiểu đầu vào đó, bao gồm cả thành phần thời gian có thể sẽ không vượt qua xác thực và khó hoặc người dùng không thể loại bỏ.
brianary

25

Có thể muốn xem bài đăng trên Blog của Kiran Chand , anh ấy sử dụng siêu dữ liệu tùy chỉnh trên mô hình chế độ xem như:

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

Điều này được kết hợp với các mẫu tùy chỉnh sử dụng siêu dữ liệu. Theo ý kiến ​​của tôi, một cách tiếp cận rõ ràng và đơn giản nhưng tôi muốn thấy trường hợp sử dụng phổ biến này được tích hợp sẵn cho mvc.


71
Bạn đang giỡn đấy à? Đây là quá nhiều quá mức cần thiết cho một điều đơn giản như vậy. Ngày càng có nhiều tôi quay trở lại HTML thuần túy và quên đi các phương thức trợ giúp cồng kềnh MVC. 5 phút trước, tôi có một TextboxFor đơn giản đã khởi chạy thành công một trình chọn ngày jquery. Bây giờ, chỉ vì tôi muốn thay đổi cách nó định dạng giá trị ngày được tải trước, tôi đã phải thay đổi nó thành EditorFor. Nhưng bây giờ đột nhiên tôi không thể chỉ định các thuộc tính HTML của riêng mình nữa nếu không viết các phương thức và trình trợ giúp tiện ích mở rộng tùy chỉnh quá cồng kềnh này. Thật là một câu chuyện hài hước. Phải có một cách đơn giản hơn, các giáo sư điên khùng không biết khi nào dừng lại.
Aaron

1
Tôi nghĩ bạn đang trộn lẫn các bối cảnh. Làm thế nào bạn có thể có hai EditorFor khác nhau cho các cuộc gọi với mỗi lệnh nhận giá trị kích thước và độ dài tối đa của riêng nó với liên kết bạn đã cung cấp? Nếu bạn không muốn sử dụng EditorFor, bạn luôn có thể sử dụng trình trợ giúp TextBox hoặc html đơn giản. Nhưng đó không phải là câu hỏi!
chandmk

@Aaron kể từ MVC mới nhất, bạn có thể chỉ định các thuộc tính html bổ sung bằng EditorForcách chuyển nó dưới dạng:new { htmlAttributes: { @class = "yourclass" } }
JoeBrockhaus

17

Tôi ngạc nhiên là không ai đề cập đến việc chuyển nó trong "addedViewData" và đọc nó ở phía bên kia.

Xem (có ngắt dòng, để rõ ràng):

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

Mẫu biên tập viên:

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

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

Xây dựng trên tôi này đã tạo ra một helper mà sẽ đưa vào tài khoản sáp nhập các thuộc tính - stackoverflow.com/a/11498094/79842
Colin Bowern

6

Vấn đề là, mẫu của bạn có thể chứa một số phần tử HTML, vì vậy MVC sẽ không biết cái nào sẽ áp dụng kích thước / lớp của bạn. Bạn sẽ phải tự xác định nó.

Tạo mẫu của bạn bắt nguồn từ lớp của riêng bạn có tên là 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
  }

}

Trong mẫu, bạn có thể làm điều này:

<input value="<%= Model.Value %>" <%= Model.GetAttributesString() %> />

Theo quan điểm của bạn, bạn làm:

<%= Html.EditorFor(x => x.StringValue) %>
or
<%= Html.EditorFor(x => new TextBoxViewModel(x.StringValue, new IDictionary<string, object> { {'class', 'myclass'}, {'size', 15}}) %>

Biểu mẫu đầu tiên sẽ hiển thị mẫu mặc định cho chuỗi. Biểu mẫu thứ hai sẽ hiển thị mẫu tùy chỉnh.

Cú pháp thay thế sử dụng giao diện thông thạo:

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) %>

Lưu ý rằng thay vì thực hiện việc này trong dạng xem, bạn cũng có thể thực hiện việc này trong bộ điều khiển hoặc tốt hơn nhiều trong 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) });
}

Cũng lưu ý rằng bạn có thể tạo lớp TemplateViewModel cơ sở - nền tảng chung cho tất cả các mẫu chế độ xem của bạn - sẽ chứa hỗ trợ cơ bản cho các thuộc tính / v.v.

Nhưng nói chung tôi nghĩ MVC v2 cần một giải pháp tốt hơn. Nó vẫn là bản Beta - hãy yêu cầu nó ;-)


Tôi nghĩ rằng một cách tốt hơn để giải quyết vấn đề này là như tôi đã đề cập ở đây stackoverflow.com/questions/1647609/… ... Nói tóm lại, làm một cái gì đó tương tự như cách WPF xử lý vấn đề ... Các phần tử kiểu tùy ý (trong trường hợp này thuộc tính) được chuyển cho template và mẫu quyết định những nội yếu tố đó sẽ áp dụng các phong cách để ...
vdhant

6

Tôi nghĩ rằng sử dụng CSS là một cách để đi. Tôi ước mình có thể làm được nhiều việc hơn với mã hóa .NET, như trong XAML, nhưng trong trình duyệt CSS là vua.

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


Điều này hoạt động rất tốt để kiểm soát các thay đổi CSS cụ thể khi sử dụng EditorFormẫu. Tôi đang sử dụng MVC4 và điều này đã hoạt động tốt.
atconway

6

Như ở MVC 5, nếu bạn muốn thêm bất kỳ thuộc tính nào, bạn chỉ cần thực hiện

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

Thông tin tìm thấy từ blog này


3

Bạn có thể xác định các thuộc tính cho các thuộc tính của mình.

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

Điều này được gọi là System.ComponentModel.DataAnnotations. Nếu bạn không thể tìm thấyValidationAttribute mình cần, bạn luôn có thể xác định các thuộc tính tùy chỉnh.

Trân trọng, Carlos


3
Anh ấy nói về các thuộc tính Html như maxlength không xác thực.
Mathias F

Tôi hy vọng công cụ xem cũng sẽ tuân theo DataAnnotations. Tôi vẫn chưa nhầm lẫn với MVC2.
mxmissile

Tôi đã thử chú thích dữ liệu StringLength. Nó không hoạt động với EditorFor.
wayne.blackmon

3

Đây có thể không phải là giải pháp khéo léo nhất, nhưng nó rất đơn giản. Bạn có thể viết một phần mở rộng cho lớp HtmlHelper.EditorFor. Trong phần mở rộng đó, bạn có thể cung cấp một tham số tùy chọn sẽ ghi các tùy chọn vào ViewData cho trình trợ giúp. Đây là một số mã:

Đầu tiên, phương pháp mở rộng:

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

Tiếp theo, đối tượng tùy chọn:

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

Và cuối cùng, đây là dòng từ mẫu String.ascx:

<%= Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = ViewData["cssClass"] ?? "" }) %>

Thành thật mà nói, tôi nghĩ điều này rất đơn giản và rõ ràng đối với tâm hồn tội nghiệp, những người phải duy trì mã của bạn trên đường. Và có thể dễ dàng mở rộng cho nhiều thông tin khác nhau mà bạn muốn chuyển đến các mẫu của mình. Nó đang hoạt động tốt cho đến nay đối với tôi trong một dự án mà tôi đang cố gắng kết hợp nhiều nhất có thể trong một bộ mẫu để giúp chuẩn hóa html xung quanh, đó là http://bradwilson.typepad.com/blog/2009/ 10 / aspnet-mvc-2-templates-part-5-master-page-templates.html .


3

Tôi đã viết một mục blog để trả lời câu hỏi của riêng tôi

Thêm hỗ trợ thuộc tính html cho Mẫu - ASP.Net MVC 2.0 Beta


Ý tưởng đặt các thuộc tính định dạng HTML trên mô hình (view) là chống lại ý tưởng của MVC để tách riêng view và logic! Điều gì sẽ xảy ra nếu mô hình cần các biểu diễn khác nhau trong HTML?
Holyedlama

2
@Saintedlama: Việc đặt chú thích dữ liệu trên viewmodel là hoàn toàn tốt , vì mục đích duy nhất của viewmodel là cung cấp mô hình dữ liệu có cấu trúc cho chế độ xem . Không nên nhầm lẫn với mô hình , trong thuật ngữ MVC thường đại diện cho một thực thể DB, không nên có bất kỳ thuộc tính nào liên quan đến chế độ xem. Phải nói rằng, thật không may khi các chú thích viewmodel của anh ấy bắt đầu bằng HTMLxxx vì điều đó ngụ ý HTML như một lớp trình bày, nhưng một dòng phải được vẽ ở đâu đó. :) Ngoài ra, nếu anh ấy sử dụng lại viewmodel cho ứng dụng silverlight, anh ấy có thể dễ dàng thêm các thuộc tính SL vào chế độ xem của mình.
Boris B.

3

Tôi không biết tại sao nó không hoạt động với Html.EditorFor nhưng tôi đã thử TextBoxFor và nó hoạt động với tôi.

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

... và xác nhận cũng hoạt động.


bạn cần@class = "className"
JoeBrockhaus

2

Trong thực tế của mình, tôi thấy rằng tốt nhất là sử dụng EditorTemplates với chỉ một HtmlHelper trong đó - TextBox trong hầu hết các trường hợp. Nếu tôi muốn một mẫu cho cấu trúc html phức tạp hơn, tôi sẽ viết một HtmlHelper riêng.

Cho rằng chúng ta có thể dán toàn bộ đối tượng ViewData vào vị trí của htmlAttributes của TextBox. Ngoài ra, chúng ta có thể viết một số mã tùy chỉnh cho một số thuộc tính của ViewData nếu chúng cần được xử lý đặc biệt:

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

Dưới đây là các ví dụ về cú pháp trong dạng xem và html được xuất:

@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

Bởi vì câu hỏi dành cho EditorFor không phải TextBoxFor gợi ý của WEFX không hoạt động.

Để thay đổi các hộp nhập riêng lẻ, bạn có thể xử lý đầu ra của phương thức EditorFor:

<%: new HtmlString(Html.EditorFor(m=>m.propertyname).ToString().Replace("class=\"text-box single-line\"", "class=\"text-box single-line my500pxWideClass\"")) %>

Cũng có thể thay đổi TẤT CẢ EditorFors của bạn vì MVC đặt lớp EditorFor cho hộp văn bản bằng .text-box , do đó bạn chỉ có thể ghi đè kiểu này, trong biểu định kiểu của bạn hoặc trên trang.

.text-box {
    width: 80em;
}

Ngoài ra, bạn có thể đặt kiểu cho

input[type="text"] {
    width: 200px;
}
  • điều này sẽ ghi đè .text-box và sẽ thay đổi tất cả các hộp văn bản đầu vào, EditorFor hoặc cách khác.

Không phải tất cả các hộp văn bản EditorFor () đều là kiểu nhập = "text". Thuộc tính DateTime dường như hiển thị dưới dạng type = "datetime".
brianary

2

Tôi cũng gặp sự cố với việc đặt chiều rộng của TextBox trong MVC3, trong khi đặt thuộc tính Clsss hoạt động cho điều khiển TextArea nhưng không hoạt động cho điều khiển TextBoxFor hoặc EditorFor:

Tôi đã thử làm theo và điều đó hiệu quả với tôi:

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

cũng trong trường hợp này Xác thực đang hoạt động hoàn hảo.


2

Một cách bạn có thể làm tròn nó là nhờ các đại biểu trên mô hình chế độ xem để xử lý việc in ra kết xuất đặc biệt như thế này. Tôi đã làm điều này cho một lớp phân trang, tôi hiển thị một thuộc tính công cộng trên mô hìnhFunc<int, string> RenderUrl để đối phó với nó.

Vì vậy, hãy xác định cách bit tùy chỉnh sẽ được viết:

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

Xuất chế độ xem cho Paginglớp:

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

... và để Pagingxem thực tế :

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

Nó có thể được coi là những vấn đề quá phức tạp nhưng tôi sử dụng những máy nhắn tin này ở khắp mọi nơi và không thể chịu được việc nhìn thấy cùng một mã soạn sẵn để hiển thị chúng.


1

CẬP NHẬT: hm, rõ ràng là điều này sẽ không hoạt động vì mô hình được truyền theo giá trị nên các thuộc tính không được bảo toàn; nhưng tôi để câu trả lời này như một ý tưởng.

Một giải pháp khác, tôi nghĩ, sẽ là thêm trình trợ giúp TextBox / etc của riêng bạn, điều này sẽ kiểm tra các thuộc tính của riêng bạn trên mô hình.

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)) %>

Điều này là dễ dàng hơn nhưng không thuận tiện / linh hoạt.



0

Tôi thực sự thích câu trả lời @tjeerdans sử dụng EditorTemplate có tên là String.ascx trong thư mục / Views / Shared / EditorTemplates. Nó dường như là câu trả lời thẳng thắn nhất cho câu hỏi này. Tuy nhiên, tôi muốn một mẫu sử dụng cú pháp Razor. Ngoài ra, có vẻ như MVC3 sử dụng mẫu Chuỗi làm mặc định (xem câu hỏi StackOverflow " mẫu hiển thị mvc cho chuỗi được sử dụng cho số nguyên ") nên bạn cần đặt mô hình thành đối tượng thay vì chuỗi. Mẫu của tôi dường như đang hoạt động cho đến nay:

@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

Tôi đã giải quyết nó !!
Đối với Razor, cú pháp là:
@Html.TextAreaFor(m=>m.Address, new { style="Width:174px" })điều này điều chỉnh chiều rộng vùng văn bản thành chiều rộng mà tôi đã xác định trong tham số kiểu.
Đối với ASPx, cú pháp là:
<%=Html.TextAreaFor(m => m.Description, new { cols = "20", rows = "15", style="Width:174px" })%>
điều này sẽ thực hiện thủ thuật

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.