Można wykonać następujące pornografii w widoku:
@model IEnumerable<Foo>
<table>
@foreach (var item in from i in Model.Select((value, index) => new { value, index }) group i.value by i.index/3 into g select g)
{
<tr>
@foreach (var x in item)
{
<td><div class="productsFrame">@x.SomeProperty</div></td>
}
</tr>
}
</table>
lub po prostu korzystać z widoku modeli i zrobić grupowanie w akcji kontrolera, który oczywiście jest to, co chciałbym Ci polecić. Sam fakt, że musisz to zrobić, oznacza, że twój model widoku nie jest dostosowany do wymagań twojego widoku, czyli do grupowania wyników przez 3. Tak więc dostosuj go. Nie należy przekazywać IEnumerable<Foo>
do widoku. Zdać IEnumerable<MyViewModel>
, gdzie oczywiście MyViewModel będzie zawierał niezbędne grupowanie, tak aby w twoich widokach można było po prostu zapętlić lub ponieważ nienawidzę pisać i pętli foreach w widokach po prostu używaj szablonów wyświetlania. Zajmą się wszystkim, a Twój widok będzie wyglądał tak:
<table>
@HtmlDisplayForModel()
</table>
Wygląda lepiej niż początkowa pornografia, prawda?
Zgodnie z prośbą w sekcji komentarzy tutaj, w jaki sposób mogę to zaimplementować przy użyciu modeli widoku.
Jako zawsze w ASP.NET aplikacji MVC zacząć od zdefiniowania widoku modeli, które odzwierciedlają wymagania widoku (co powtarzam to: pokaż tabelę z 3 kolumnami):
public class ItemViewModel
{
public string Title { get; set; }
}
public class MyViewModel
{
public IEnumerable<ItemViewModel> Items { get; set; }
}
następnie przenieść się do kontrolera, który wypełni i zdać ten widok modelu do widoku:
public class HomeController : Controller
{
public ActionResult Index()
{
// Obviously in a real world application the data is your domain model
// and comes from a repository or a service layer depending on the complexity
// of your application. I am hardcoding it here for the
// purposes of the demonstration
var data = Enumerable.Range(1, 30).Select(x => new { Title = "title " + x });
var model =
from i in data.Select((value, index) => new { value, index })
group i.value by i.index/3 into g
select new MyViewModel
{
Items = g.Select(x => new ItemViewModel { Title = x.Title })
};
return View(model);
}
}
i wreszcie napisać odpowiedni widok (~/Views/Home/Index.cshtml
):
@model IEnumerable<MyViewModel>
<table>
@Html.DisplayForModel()
</table>
i ~/Views/Home/DisplateTemplates/MyViewModel.cshtml
wyświetlacz szablon:
@model MyViewModel
<tr>
@Html.DisplayFor(x => x.Items)
</tr>
i wreszcie odpowiedni szablon ~/Views/Home/DisplateTemplates/ItemViewModel.cshtml
display:
@model ItemViewModel
<td>@Html.DisplayFor(x => x.Title)</td>
i to dość dużo. Proste, czyste, zgodne z dobrymi praktykami i konwencjami.
Oczywiście, aby doprowadzić ten krok dalej byś wprowadzenia AutoMapper przeprowadzić rzeczywiste odwzorowanie pomiędzy swoimi model domeny i widoków modeli i będzie skończyć z bardzo eleganckie rozwiązanie, które będzie wyglądać następująco:
public ActionResult Index()
{
IEnumerable<DomainModel> data = ...
var viewModel = Mapper.Map<IEnumerable<DomainModel>, IEnumerable<MyViewModel>>(data);
return View(viewModel);
}
lub krok dalej:
[AutoMap(typeof(IEnumerable<DomainModel>), typeof(IEnumerable<MyViewModel>))]
public ActionResult Index()
{
IEnumerable<DomainModel> data = ...
return View(data);
}
Teraz zaczynamy się poważnie interesować.
To pytanie tak naprawdę nie ma dla mnie sensu. Jeśli masz 3 przedmioty w swoim obiekcie Model.ArticlesOnFirstSite, to właśnie to otrzymasz. –
Chcesz trzy pętle łącznie, lub chcesz trzy pętle dla każdej articleOnFirstPage? – Maess
'Model.ArticlesOnFirstSite.Take (3)'? – asawyer