2012-06-29 66 views
62

Tôi nghe nói rằng có @foreach bên trong chế độ xem là không có. Có nghĩa là, khung nhìn không nên có bất kỳ logic nào trong đó. Thực hành tốt nhất về vị trí logic của @foreach nên ở đâu?MVC Razor @foreach

@foreach.. 
+2

Bạn đã đọc cái đó ở đâu? Logic là những gì dao cạo có nghĩa là cho! –

+3

vui lòng đọc hướng dẫn sau của MS http://www.asp.net/web-pages/tutorials/basics/2-introduction-to-asp-net-web-programming-using-the-razor-syntax –

Trả lời

130

thực hành tốt nhất về nơi logic cho @foreach nên có là gì?

Không đâu, chỉ cần loại bỏ nó. Bạn có thể sử dụng trình soạn thảo hoặc mẫu hiển thị.

Vì vậy, ví dụ:

@foreach (var item in Model.Foos) 
{ 
    <div>@item.Bar</div> 
} 

có thể hoàn toàn tốt đẹp được thay thế bằng một mẫu màn hình:

@Html.DisplayFor(x => x.Foos) 

và sau đó bạn sẽ xác định các mẫu màn hình tương ứng (nếu bạn không thích những default one). Vì vậy, bạn sẽ xác định một mẫu tái sử dụng ~/Views/Shared/DisplayTemplates/Foo.cshtml đó sẽ tự động được đưa ra bởi một khuôn khổ cho mỗi phần tử của bộ sưu tập Foos (IEnumerable<Foo> Foos { get; set; }):

@model Foo 
<div>@Model.Bar</div> 

Rõ ràng chính xác các quy ước tương tự áp dụng cho các mẫu biên tập mà nên được sử dụng trong trường hợp bạn muốn hiển thị một số trường nhập cho phép bạn chỉnh sửa mô hình xem ngược lại để chỉ hiển thị nó dưới dạng chỉ đọc.

+0

Tôi đồng ý với @DarinDimitrov rằng ví dụ thứ hai trông và đọc tốt hơn.Mặc dù tôi không thấy một vấn đề với một vòng lặp foreach bên trong màn hình hiển thị một trong hai! –

+0

@NicholasKing, có vấn đề với việc tạo tên riêng cho các trường nhập của mẫu trình soạn thảo. Ví dụ chỉ cần nhìn vào [câu trả lời của Noobsyke] (http://stackoverflow.com/a/11261698/29407) bên dưới. Thay thế DisplayFor của mình bằng EditorFor và trình kết nối mô hình sẽ không hoạt động vì anh ta không tôn trọng các quy ước. –

+2

@DarinDimitrov thats true nếu một mô hình MVC nghiêm ngặt của bạn bạn đang mã hóa chống lại tuy nhiên nếu một tình huống phát sinh nơi một bộ sưu tập cần phải được looped qua đó không phải là trong mô hình, tôi không thấy một vấn đề với việc sử dụng foreach –

11

Tôi đang sử dụng @foreach khi tôi gửi một thực thể có chứa một danh sách các thực thể (ví dụ để hiển thị 2 lưới trong 1 xem)

Ví dụ nếu tôi gửi như mô hình thực thể Foo có chứa Foo1(List<Foo1>)Foo2(List<Foo2>)

tôi có thể tham khảo danh sách đầu tiên với:

@foreach (var item in Model.Foo.Foo1) 
{ 
    @Html.DisplayFor(modelItem=> item.fooName) 
} 
74

Khi mọi người nói không đặt logic trong quan điểm, chúng thường đề cập đến logic kinh doanh, không render logic. Theo quan điểm khiêm tốn của tôi, tôi nghĩ rằng việc sử dụng @foreach trong quan điểm là hoàn toàn tốt đẹp.

+15

Đồng ý. Nhắc tôi về các cuộc tranh luận HTML ngữ nghĩa cũ, cuối cùng khiến mọi người cố gắng sử dụng div và CSS để tạo ra một "bảng" cho dữ liệu bảng thực tế, bởi vì chúng rất chống bàn. –

+1

Tôi đồng ý. Con người xấu về hướng sai. Tôi có thực sự cần một thư mục mới, với một cái nhìn mới, chỉ để hiển thị những thứ trong một danh sách trong viewmodel của tôi? – mmcrae

+0

Sẽ không sử dụng div/css để tạo chế độ xem dữ liệu dạng bảng là cần thiết để tạo chế độ xem phản hồi? – frostshoxx

6

trả lời @DarinDimitrov cho trường hợp tôi đã sử dụng foreach ở chế độ xem dao cạo.

<li><label for="category">Category</label> 
     <select id="category"> 
      <option value="0">All</option> 
      @foreach(Category c in Model.Categories) 
      { 
       <option title="@c.Description" value="@c.CategoryID">@c.Name</option> 
      } 
     </select> 
</li> 
+6

WOW người đàn ông, bạn sẽ viết một cái gì đó như thế này trong một cái nhìn? Tại sao không viết một helper tùy chỉnh có thể tái sử dụng à la 'Html.DropDownListFor' mà đơn giản sẽ đưa vào tài khoản tiêu đề? Đó là tầm thường và không biến quan điểm của bạn thành mã spaghetti: http://stackoverflow.com/a/7938038/29407 –

+7

@DarinDimitrov vâng, chúng tôi làm việc trong một môi trường rất nhanh, có nghĩa là các tình huống như thế này đôi khi ngăn chúng tôi sử dụng những thứ như DropDownFor như chúng tôi không luôn luôn có một yêu cầu xác định rõ ràng. Tôi tin rằng trong trường hợp này thả xuống ban đầu không cần "tất cả" sau đó nó đã làm nhưng chỉ trong một DropDown trên xem. Vì trang này sử dụng ajax để cập nhật không phải mẫu MVC nghiêm ngặt và bạn không thể tải sản phẩm lên tất cả các danh mục theo yêu cầu. Không lý tưởng nhưng đôi khi không thể tránh khỏi. –

+0

Có lẽ một ví dụ tốt hơn sẽ sử dụng điều này để hiển thị các phần tử 'optgroup' trong danh sách lựa chọn, vì không có hỗ trợ cho điều đó trong HtmlHelpers. Nếu bạn chỉ cần thêm một mục bổ sung vào danh sách lựa chọn, có những cách tốt hơn để đạt được điều đó và sau đó vẫn sử dụng trình trợ giúp. –

2

The answer sẽ không hoạt động khi sử dụng quá tải để chỉ ra mẫu @Html.DisplayFor(x => x.Foos, "YourTemplateName).

Dường như được thiết kế theo cách đó, see this case. Ngoài ra, ngoại trừ khuôn khổ cho phép (về loại không được như mong đợi) là khá gây hiểu lầm và bị lừa tôi lần thử đầu tiên (nhờ @CodeCaster)

Trong trường hợp này bạn phải sử dụng @foreach

@foreach (var item in Model.Foos) 
{ 
    @Html.DisplayFor(x => item, "FooTemplate") 
} 
+0

Câu trả lời đó được viết bởi một người làm việc trên MVC, vì vậy tôi đoán họ biết họ đang nói gì. MVC sẽ lặp lại 'IEnumerable ' và gọi mẫu cho kiểu 'T' cho mỗi phần tử. – CodeCaster

+0

Về chỉnh sửa của bạn: đó là mã của bạn sai hoặc lỗi trong phiên bản MVC cụ thể đó (trong 5.2.2 nó hoạt động đối với tôi). Nó được cho là hoạt động như được mô tả trong câu trả lời được chấp nhận. Thay vì nói rằng đó là sai, hãy mở câu hỏi của riêng bạn về vấn đề nếu bạn muốn. – CodeCaster

+0

@CodeCaster Tôi tin rằng câu trả lời của tôi cho biết thêm một số đầu cho trường hợp cụ thể đó (nó lãng phí một số thời gian của tôi để tìm ra những gì đã đi sai). Bạn sẽ vui lòng thêm một số lời giải thích cho việc giữ downvote? (Cảm ơn thời gian của bạn btw, chỉ muốn để có được dưới cùng của sự vật) –

Các vấn đề liên quan