Wie variiere ich mein ItemTemplate innerhalb einer asp:Repeater?
Ich habe ein user-control, welches verwendet wird zur Anzeige von Suchergebnissen. Der HTML-Code für jedes Ergebnis angezeigt werden, hängt von der Art des Ergebnisses angezeigt werden: "Kontakte" angezeigt werden, in einer Weise, "news-Artikel" angezeigt werden, in einem anderen, etc. Es gibt rund 10 verschiedene Arten von Ergebnissen, die sind alle markiert, anders, wenn Sie HTML — von daher muss ich um 10 oder so verschiedene templates für einzelne Ergebnisse, die kann ich wählen zwischen, basierend auf dem aktuellen Element angezeigt wird.
Ich bin mit einem asp:Repeater
um die Ergebnisse anzuzeigen, aber ich weiß nicht, wie zu wählen Sie die entsprechende Vorlage in der asp:Repeater <ItemTemplate>
. Im Idealfall möchte ich, dass das ASP-wählen Sie die entsprechende Vorlage zu verwenden, basierend auf dem Typ des Objekts übergeben wird, die über den searchResultsRepeater.DataSource
— aber leider kann ich nicht verwenden, schalten Typ (siehe dieser blog-Eintrag für die C# - switch-on-Typ). Ich kann allerdings nur passieren, einen enum-Wert für den Typ des Ergebnisses angezeigt wird.
Im backend C# - code habe ich eine abstrakte inline SearchResult
Klasse, und die Kinder der Klasse wie ContactSearchResult
NewsArticleSearchResult
usw. Die searchResultsRepeater.DataSource
würde dann gebunden werden, um eine List<SearchResult>
. Jeder SearchResult
enthält eine ResultListingType type
Feld gibt den Typ der Liste angezeigt werden.
Versuch 1: mit control-flow innerhalb des ASP selbst
Mein Erster Versuch war so etwas wie dieses:
<asp:Repeater ID="searchResultsRepeater" runat="server">
<ItemTemplate>
<div class="item">
<% switch (DataBinder.Eval(Container.DataItem, "type")) { %>
<% case ResultListingType.CONTACT: %>
<p><%# DataBinder.Eval(Container.DataItem, "firstName") %></p>
<p><%# DataBinder.Eval(Container.DataItem, "lastName") %></p>
<% break; %>
<% case ResultListingType.NEWS: %>
<p><%# DataBinder.Eval(Container.DataItem, "newsHeadline") %></p>
<p><%# DataBinder.Eval(Container.DataItem, "newsDate") %></p>
<% break; %>
<% Case AnotherTypeOfListing1: %>
<% Case AnotherTypeOfListing2: %>
<% Case AnotherTypeOfListing3: %>
<% Case AnotherTypeOfListing4: %>
<% Case AnotherTypeOfListing5: %>
<% etc... %>
<% } %>
</div>
</ItemTemplate>
</asp:Repeater>
Leider funktioniert das nicht:
- "switch" und "wenn" beide geben "invalid expression term" in der
<%# ... %>
Klammern. - "- Container.DataItem" gibt "den Namen "Container" existiert nicht im aktuellen Kontext" innerhalb
<% ... %>
Klammern.
Versuch 2: Einstellung asp:PlaceHolder ist auf Visible = False
Fand ich etwas, das aussah nützlich bei so ändern Sie die ItemTemplate verwendet in einem asp:repeater?. Dann habe ich versucht, so etwas wie:
<asp:Repeater ID="searchResultsRepeater" runat="server">
<ItemTemplate>
<div class="item">
<asp:PlaceHolder ID="newsResultListing" runat="server">
<p><%# DataBinder.Eval(Container.DataItem, "newsHeadline") %></p>
<p><%# DataBinder.Eval(Container.DataItem, "newsDate") %></p>
</asp:PlaceHolder>
<asp:PlaceHolder ID="contactResultListing" runat="server">
<p><%# DataBinder.Eval(Container.DataItem, "firstName") %></p>
<p><%# DataBinder.Eval(Container.DataItem, "lastName") %></p>
</asp:PlaceHolder>
</div>
</ItemTemplate>
</asp:Repeater>
In meinem ItemDataBound-Ereignis habe ich:
Control newsResultListing = e.Item.FindControl("newsResultListing");
newsResultListing.Visible = false;
Control contactResultListing = e.Item.FindControl("contactResultListing");
contactResultListing.Visible = false;
switch (item.type)
{
case ResultListingType.CONTACT:
contactResultListing.Visible = true;
break;
case ResultListingType.NEWS:
newsResultListing.Visible = true;
break;
default:
throw new Exception("Unknown result listing type");
}
Leider funktioniert das nicht, weil ASP scheint noch ausgeführt werden, den Inhalt der Platzhalter, auch nachdem ich Visible = false
. Ich bekomme die Fehlermeldung "DataBinding: 'usercontrols_ResultsListing+ContactResultsListing" enthält keine Eigenschaft mit dem Namen 'newsHeadline'" — D. H. die newsResultListing
Platzhalter ist noch auf der Suche nach der "newsHeadline" - Feld, obwohl das Feld existiert nicht für die Ergebnis-Liste Typ angezeigt wird.
In der Tat habe ich versucht, ein quick-test throw new Exception("e");
in meinem ItemDataBound, und es sieht aus wie das "Binding" - Fehler geworfen wird, noch bevor die Kontrolle Fluss bekommt das ItemDataBound-Methode, also es gibt wirklich nichts, was ich tun kann, in der es um diesen Fehler zu vermeiden.
Ich nehme an, ich könnte hinzufügen, jedes einzelne Feld zu der übergeordneten Klasse und lassen die meisten von Ihnen null in meine Kinder, aber das scheint wirklich hässlich.
Gibt es eine Möglichkeit, diese Arbeit zu machen, oder eine einfachere Möglichkeit zu variieren meine ItemTemplate basierend auf der Art von Container.DataItem ich bin derzeit Durchlaufen? Ich bin sehr neu in ASP ist wahrscheinlich etwas einfach, dass ich es verpasst habe. 🙂
InformationsquelleAutor der Frage George | 2011-04-04
Du musst angemeldet sein, um einen Kommentar abzugeben.
OK, ich denke ich habe eine Lösung gefunden — ich habe mehrere zusätzliche Benutzer-Steuerelemente, eine für jede Art von suchergebnis. Jedes dieser Steuerelemente definiert die HTML-Vorlage für den entsprechenden Typ von suchergebnis.
Meine
asp:Repeater
enthält absolut nichts in seinemItemTemplate
:Ich bind ein
List<SearchResultData>
zu meinemasp:Repeater
wie vor, und nach wie vor diese Liste enthält weitere spezifische Subtypen vonSearchResultData
basierend auf dem Typ des Ergebnisses angezeigt werden.In meinem
ItemDataBound
- handler instanziieren ich einer dieser Benutzer steuert, basierend auf dem Typ der Daten ine.Item.DataItem
und dann legen Sie das Benutzersteuerelement in den repeater:InformationsquelleAutor der Antwort George
Hinzufügen George ' s Lösung, die
<ItemTemplate>
sich um eine Mischung von markup und dynamische Steuerelemente. Das folgende Beispiel erzeugt eine Tabelle mit name/Wert-Paaren.Code-behind -
InformationsquelleAutor der Antwort Doug Domeny
Müssen Sie überschreiben das ItemDataBound-Ereignis-handler und-Kontrolle es gibt.
Alternativ, setzen Sie die Logik in einem user-Steuerelement und dem Benutzer die Kontrolle in der Vorlage statt.
Dem Benutzer die Kontrolle wird noch implementieren müssen, um die entsprechende Umstellung, aber es erleichtert die Wiederverwendung der Logik.
InformationsquelleAutor der Antwort Roger Willcocks