2009-10-26 5 views
111

Asp.Net MVC 2.0 preview xây dựng cung cấp người giúp đỡ nhưEditorFor() và html tính

Html.EditorFor(c => c.propertyname) 

Nếu tên tài sản là chuỗi, các mã trên ám một texbox.

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 thì sao?

Tôi có cần tạo một mẫu cho từng kích thước và kết hợp độ 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.

Trả lời

3

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

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

+0

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

+2

@Saintedlama: Bạn nên đặt chú thích dữ liệu trên * viewmodel *, 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 được nhầm lẫn với * model *, trong thuật ngữ MVC thường đại diện cho một thực thể DB, mà không nên có bất kỳ thuộc tính liên quan đến khung nhìn nào. Có nói rằng, nó là không may rằng chú thích viewmodel của mình bắt đầu với HTMLxxx bởi vì điều đó ngụ ý HTML như là một lớp trình bày, nhưng một dòng đã được rút ra ở đâu đó. :) Bên cạnh đó, nếu anh ta sử dụng lại viewmodel để nói ứng dụng Silverlight, anh ta có thể dễ dàng thêm các thuộc tính SL vào viewmodel của mình. –

3

Bạn có thể xác định thuộc tính cho 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ấy ValidationAttribute mà bạn cần, bạn có thể xác định các thuộc tính tùy chỉnh.

Best Regards, Carlos

+3

Ông nói về Html-thuộc tính như maxlength không xác nhận. –

+0

Tôi sẽ * hy vọng * công cụ xem cũng sẽ tuân theo DataAnnotations. Tôi đã không rối tung với MVC2. – mxmissile

+0

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

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 phải cái nào để áp dụng kích thước của bạn/lớp. Bạn sẽ phải tự định nghĩa nó.

Hãy mẫu của bạn bắt nguồn từ lớp học của bạn riêng gọi 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 cầ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.

Alternative sử dụng cú pháp thông thạo giao diện:

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

ý rằng thay vì làm điều này trong giao diện, bạn cũng có thể làm điều này trong đ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ở - một nền tảng chung cho tất cả các mẫu xem của bạn - sẽ chứa các 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 còn Beta - hãy yêu cầu nó ;-)

+0

Tôi nghĩ rằng một cách tốt hơn để đối phó với điều này là như tôi đã đề cập ở đây http: //stackoverflow.com/questions/1647609/asp-net-mvc-v2-styling-templates ... Trong ngắn hạn làm một cái gì đó tương tự như cách mà WPF xử lý vấn đề ... Các yếu tố phong cách tùy ý (trong trường hợp này thuộc tính) được chuyển đến mẫu và mẫu quyết định phần tử bên trong nào sẽ áp dụng kiểu ... – vdhant

1

CẬP NHẬT: hm, rõ ràng điều này sẽ không hoạt động vì mô hình được truyền theo giá trị để các thuộc tính không được giữ nguyên; nhưng tôi để lạ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ẽ thêm người trợ giúp TextBox/etc của riêng bạn, điều đó 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)) %> 

Cái này dễ hơn nhưng không thuận tiện/linh hoạt.

25

thể muốn nhìn vào Kiran Chand's Blog post, ông sử dụng siêu dữ liệu tùy chỉnh trên mô hình điểm như:

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

này được kết hợp với các mẫu tùy chỉnh mà tận dụng các siêu dữ liệu. Một cách tiếp cận sạch sẽ và đơn giản trong quan điểm của tôi nhưng tôi muốn thấy trường hợp sử dụng phổ biến này được xây dựng trong mvc.

+71

Bạn đang đùa à? Đây là quá nhiều quá mức cần thiết cho một điều đơn giản như vậy. Càng ngày tôi càng trở lại với HTML thuần túy và quên đi các phương thức trợ giúp cồng kềnh của 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 đếm ngày tháng jquery. Bây giờ chỉ vì tôi muốn thay đổi cách định dạng giá trị ngày được tải trước, tôi phải thay đổi nó thành một 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 tôi nữa mà không cần viết các phương thức mở rộng tùy chỉnh quá mức và người trợ giúp 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 biết khi nào nên 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 cuộc gọi EditorFor khác nhau với mỗi cuộc gọi có kích thước và giá trị maxlength riêng 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

+0

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

3

Đây có thể không phải là giải pháp mượt mà nhất, nhưng nó rất đơn giản. Bạn có thể viế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ẽ viết các tùy chọn cho ViewData cho trình trợ giúp. Dưới đây là một số mã:

Thứ nhất, phương pháp khuyến nô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, các tùy chọn đối tượng:

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 là đơn giản và rõ ràng đối với linh hồn nghèo nàn, những người phải duy trì mã của bạn wn đường. Và nó rất dễ dàng để mở rộng cho các bit khác của thông tin bạn muốn chuyển đến các mẫu của bạn. Nó làm việc tốt cho đến nay đối với tôi trong một dự án mà tôi đang cố gắng bọc càng nhiều càng tốt trong một bộ mẫu để giúp chuẩn hóa html xung quanh, a la http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-5-master-page-templates.html.

61

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

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

trình như một nét duyên dáng cho tôi!

+1

rực rỡ - Tôi có một trình đếm ngày Datepicker thả xuống mà tôi 'd đã được templated, nhưng đi qua các thuộc tính phụ để nó đã được chứng minh đau đớn - điều này giải quyết nó cho tôi, cảm ơn! –

+0

EditorFor với maxlength không hoạt động cho tôi (TextBoxFor trên khác không) – Drejc

+0

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

89

Trong MVC3, bạn có thể thiết lập chiều rộng như sau:

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

@vondip. Hãy chắc chắn rằng một TEXTBOX của nó và không phải là một EDITOR. Doenst làm việc với trình soạn thảo. –

+1

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

+0

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

3

Tôi không biết tại sao nó không làm việc cho Html.EditorFor nhưng tôi đã cố gắng TextBoxFor và nó làm việc cho tôi.

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

... và cũng xác thực hoạt động.

+0

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

15

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

Xem (với ngắt dòng, cho rõ ràng):

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

biên tập mẫu:

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

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

Xây dựng trên trang này tôi đã tạo một trình trợ giúp tính đến việc hợp nhất các thuộc tính - http://stackoverflow.com/a/11498094/79842 –

+0

cách tuyệt vời để 'giải pháp' gây phiền toái 'thiếu tính năng' –

2

Trong thực tế, tôi thấy rằng nó là tốt nhất để sử dụng EditorTemplates chỉ với một HtmlHelper trong đó - TextBox đó là trong nhiều 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 biệt.

Cho rằng chúng ta có thể dán toàn bộ đối tượng ViewData thay cho htmlAttributes của TextBox. Bên cạnh đó chúng tôi có thể viết một số mã tùy biến cho một số các thuộc tính của ViewData nếu họ cần điều trị đặ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à những ví dụ về cú pháp trong giao diện và html outputted:

@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"> 
33

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

Styling an @Html.EditorFor helper

tôi đã sử dụng phương pháp tương tự và nó làm việc thật đẹp mà không cần viết nhiều mã thêm. Lưu ý rằng thuộc tính id của đầu ra html của Html.EditorFor được đặt. Mã 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 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 nét duyên dáng mà không cần viết một toàn bộ rất nhiều mã thêm. Câu trả lời này sử dụng ASP.NET MVC 3 Razor C#.

+1

giải pháp tốt nhất nó hoạt động tuyệt vời cho tôi !!! –

+1

Làm việc thực sự tốt cho tôi trong MVC4. – atconway

+1

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

2

Vì câu hỏi là dành cho EditorFor không phải TextBoxĐề xuất của WEFX không hoạt động.

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

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

Nó cũng có thể thay đổi tất cả EditorFors của bạn khi nó quay ra MVC thiết lập lớp của hộp văn bản EditorFor với .text-box, do đó bạn chỉ có thể ghi đè kiểu này, trong biểu định kiểu hoặc trên trang.

.text-box { 
    width: 80em; 
} 

Ngoài ra, bạn có thể thiết lập phong cách cho

input[type="text"] { 
    width: 200px; 
} 
  • 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 hay không.
+0

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

0

Tôi thực sự thích câu trả lời @tjeerdans sử dụng EditorTemplate có tên String.ascx trong thư mục/Views/Shared/EditorTemplates. Nó có vẻ 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 có một mẫu sử dụng cú pháp Razor. Ngoài ra, có vẻ như MVC3 sử dụng mẫu String làm mặc định (xem câu hỏi StackOverflow "mvc display template for strings is used for integers") vì vậy bạn cần đặt mô hình thành đối tượng thay vì chuỗi. Mẫu của tôi có vẻ đang hoạt động cho đến thời điểm này:

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

Tôi nghĩ rằng việc sử dụng CSS là cách để thực hiện. Tôi ước tôi có thể làm được nhiều hơn với mã hóa .NET, như trong XAML, nhưng trong CSS của trình duyệt 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

+0

Công cụ này hoạt động rất tốt để thực hiện các thay đổi CSS cụ thể về kiểm soát khi sử dụng mẫu 'EditorFor'. Tôi đang sử dụng MVC4 và điều này làm việc tuyệt vời. – atconway

2

Tôi cũng đã có vấn đề với thiết lập độ rộng của TextBox trong MVC3, trong khi thiết lập các thuộc tính Clsss làm việc để kiểm soát TextArea nhưng không phải cho điều khiển TextBoxFor hoặc EditorFor:

Tôi Ried sau & mà làm việc cho tôi:

@ Html.TextBoxFor (mô hình => 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 đó là nhờ các đại biểu trên mô hình 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 trưng ra một tài sản công cộng trên mô hình Func<int, string> RenderUrl để giải quyết nó.

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

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

Output quan điểm cho lớp Paging:

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

... và cho thực tế Paging xem:

@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 xem là vấn đề quá phức tạp nhưng tôi sử dụng các trang này ers ở khắp mọi nơi và không thể đứng nhìn thấy cùng một mã boilerplate để có được chúng rendered.

5

Tại MVC 5, nếu bạn muốn thêm bất kỳ thuộc tính bạn có thể chỉ cần làm

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

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

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 chỉnh độ rộng của vùng văn bản theo 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" })%>
này sẽ làm các trick