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 ContactSearchResultNewsArticleSearchResult 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

Schreibe einen Kommentar