2010-08-05 17 views
31

Jestem kochający MVC 2. Cała ta rzecz tak dobrze pasuje do sieci.Jak mogę użyć Html.DisplayFor wewnątrz iteratora?

Jest jeden kawałek funkcjonalności jednak, że nie jestem w stanie namówić z funkcji Html.DisplayFor():

<@ Page Inherits="ViewPage<IEnumerable<Foo>>"> 

<% foreach(var item in Model) { %> 

    <%: Html.DisplayFor(item.BarBaz) %> 

<% } %> 

muszę być w stanie korzystać z DisplayTemplate dla tej wartości. Czy jest jakiś sposób na zrobienie tego?

Odpowiedz

63

Właściwie to rozgryzłem. Ale jestem głupi.

to działa:

<@ Page Inherits="ViewPage<IEnumerable<Foo>>"> 

<% foreach(var item in Model) { %> 

    <%: Html.DisplayFor(m => item.BarBaz) %> 

<% } %> 
+2

Myślę, że jestem jeszcze bardziej głupi, ponieważ nie jestem pewien, jak to interpretować. Formalny parametr lambda m nie jest używany w wyrażeniu. Czy jest to tylko tam, ponieważ jest wymagane przez _DisplayFor_? Ponadto, oczekiwałem, że '@ Html.Display (item.BarBaz)' będzie działał równie dobrze, ale to niczego nie renderuje. –

+0

@ R.Schreurs Wydaje się, że lambda musi być wyrażeniem "Func", które przyjmuje typ modelu jako parametr, ale może zwrócić wszystko. – JohnnyHK

+0

Jestem też głupi :) –

10

Można ją osiągnąć poprzez uzyskanie od foreach i przy użyciu zwykłej pętli for:

<% for (int i = 0; i < Model.Count(); i++) { %> 

    <%: Html.DisplayFor(p=> p.ElementAt(i).BarBaz) %> 

<%} %> 

Innym rozwiązaniem byłoby stworzenie PartialView które miały obiektu Foo i wyświetlane tylko informacje, które chciał.

<% foreach (var item in Model) 
    { 
     Html.RenderPartial("FooBarBazLine", item); 
    } %> 
+1

lubię opcja 2 lepiej – Necros

+1

+1 ale jestem z Necros/opcja 2 jest znacznie czystsze – Tahbaza

+1

Zgadzam się, że opcja 2 jest lepszym rozwiązaniem. Właśnie dodałem opcję 1, ponieważ myślałem o tym po raz pierwszy i nie miałem żadnego powodu, aby ją usunąć, ponieważ rozwiązuje ona problem. – sgriffinusa

3

Html.DisplayFor może automatycznie iteracyjne nad zbiorami, wyświetlając częściowy widok dla każdego elementu w kolekcji.

Pierwszą rzeczą, którą musisz zrobić, to stworzyć rzeczywistą klasę modelu, której kolekcja jest własnością klasy.

public class Bar 
{ 
    public IEnumerable<Foo> foo { get; set; } 
} 

Powróć tę klasę ze swojego kontrolera zamiast z surowej kolekcji.

Po drugie potrzebujesz szablonu wyświetlania dla klasy Foo. Szablony wyświetlania to widoki częściowe, które należy umieścić w folderze Views/Shared/DisplayTemplates.

Edytuj: Możesz je również umieścić w podfolderze kontrolera w widokach, jeśli chcesz ograniczyć szablon do określonego kontrolera. Aby uzyskać więcej informacji, patrz this question.

Oto przykład składni brzytwa:

@model YourNameSpace.Foo 
<p>@Model.BarBaz</p> 

zapisać go jako Foo.cshtml w folderze DisplayTemplates podanym powyżej.

Ten szablon jest dość prosty, ponieważ opiera się na przykładzie, w którym wyświetlasz tylko ciąg znaków, ale jeśli elementy kolekcji, w których klasa ma własne właściwości, możesz utworzyć bardziej złożony szablon.

Teraz w oryginalnym widoku można pozbyć pętli całkowicie i po prostu napisać

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

Wskazówka foo to nazwa obiektu w nowej klasie modelu, który zawiera starą kolekcję masz zapętlone nad przed .

Displayfor automatycznie wiedzieć, że nieruchomość foo jest typu (zbieranie) Foo i podnieść szablon w folderze DisplayTemplatesFoo.cshtml i pokazać go raz dla każdego elementu foo.

+0

Wyobraź sobie, że masz mnóstwo modeli, mając takie listy ** IEnumerable **. Czy stworzysz jeden szablon na tysiąc jednostek? Wszystko, czego potrzebujesz, to po prostu ogólny szablon dla podstawowych typów, takich jak string, integer, boolean itd. – Alexander

+0

Naprawdę nie potrzebujesz paska, jeśli kolekcja foo jest dostępna, na przykład statycznie? Lub jest to tylko zmienna lokalna? – toddmo

6

To stara sprawa, ale myślę, że ktoś może uzyskać korzyści z mojego rozwiązania:

widoku Aspx

<%@ Page Inherits="ViewPage<IEnumerable<Foo>>" %> 

<% foreach (var item in Model) { %> 

    <%: Html.DisplayFor(m => item) %> 

<% } %> 

widoku Razor

@model IEnumerable<Foo> 

@foreach (var item in Model) 
{ 
    Html.DisplayFor(m => item) 
} 

Od DisplayFor akceptuje domyślną lambda, możemy bezpośrednio wskazać instanc e, aby wyświetlić w pętli.

Wreszcie jestem zgodzić się z odpowiedzią Anders E. Andersen „s do użycia szablonów

0

W Razor Używam

@Html.DisplayFor(model => item.CreatedDate) 
Powiązane problemy