如何在asp:Repeater中改变我的ItemTemplate?

Geo*_*rge 13 c# asp.net

我有一个用户控件,用于显示搜索结果.显示的每个结果的HTML将根据显示的结果类型而变化:"联系人"以一种方式显示,"新闻文章"显示在另一种中,等等.大约有10种不同类型的结果都被标记出来当他们使用HTML时会有所不同 - 所以我需要大约10个不同的模板用于个别结果,我可以根据显示的当前项目进行选择.

我用a asp:Repeater来显示结果,但我不知道如何选择合适的模板asp:Repeater <ItemTemplate>.理想情况下,我希望ASP根据通过searchResultsRepeater.DataSource- 传入的对象类型选择合适的模板使用- 但不幸的是我不能使用switch on type(请参阅此博客条目,了解C#switch on type).但是,我可以通过枚举值来显示所显示的结果类型.

在后端C#代码,我有一个抽象内嵌SearchResult类,并且该类的孩子喜欢ContactSearchResult,NewsArticleSearchResult等searchResultsRepeater.DataSource将被绑定到List<SearchResult>.每个字段都SearchResult包含一个ResultListingType type字段,用于显示要显示的列表类型.

尝试1:在ASP本身内部使用控制流程

我的第一次尝试是这样的:

        <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>
Run Code Online (Sandbox Code Playgroud)

不幸的是,这不起作用:

  • "switch"和"if"都在<%# ... %>括号内给出"无效表达术语" .
  • "Container.DataItem"在<% ... %>括号内给出"名称"容器"当前上下文中不存在" .

尝试2:将asp:PlaceHolder设置为Visible = False

我找到了一些对于如何更改asp:repeater中使用的ItemTemplate有用的东西?.然后我尝试了类似的东西:

        <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>
Run Code Online (Sandbox Code Playgroud)

在我的ItemDataBound事件中,我做了:

        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");
        }
Run Code Online (Sandbox Code Playgroud)

不幸的是,这不起作用,因为即使我设置了ASP,ASP似乎仍然在运行PlaceHolder的内容Visible = false.我收到错误"DataBinding:'usercontrols_ResultsListing + ContactResultsListing'不包含名为'newsHeadline'的属性" - 即newsResultListingPlaceHolder仍然在寻找"newsHeadline"字段,即使结果列表中不存在该字段正在显示的类型.

实际上我已经throw new Exception("e");在我的ItemDataBound中尝试了一个快速测试,看起来甚至在控制流到达ItemDataBound方法之前就抛出了"DataBinding"错误,因此我无法在那里做任何事情来避免这个错误.

我想我可以将每个字段添加到父类中,并将大部分字段留给我的孩子,但这看起来真的很难看.


有没有办法让这个工作,或更容易的方式来改变我的ItemTemplate基于我正在迭代的Container.DataItem的类型?我对ASP很陌生,所以我可能会错过一些简单的东西.:)

Geo*_*rge 14

好的,我想我找到了一个解决方案 - 我已经创建了多个额外的用户控件,每个用户控件对应一种类型的搜索结果.这些控件中的每一个都为其相应类型的搜索结果定义HTML模板.

我的asp:Repeater内容绝对没有ItemTemplate:

    <asp:Repeater ID="searchResultsRepeater" runat="server">
        <ItemTemplate>
            <%-- empty template: we insert usercontrols in the ItemDataBound --%>
        </ItemTemplate>
    </asp:Repeater>
Run Code Online (Sandbox Code Playgroud)

List<SearchResultData>我asp:Repeater像以前一样绑定到my ,并且在此列表之前包含SearchResultData基于要显示的结果类型的更具体的子类型.

在我的ItemDataBound处理程序中,我根据数据类型实例化其中一个用户控件e.Item.DataItem,然后将该用户控件插入到转发器中:

        var aspxItem = e.Item;
        var dataItem = (SearchResultData) e.Item.DataItem;

        if (dataItem is ContactSearchResult.ContactSearchResultData)
        {
            var contactSearchResultUC = LoadControl("~/UserControls/ResultsListingSearchResult/ContactSearchResult.ascx") as ASP.ContactSearchResult;
            contactSearchResultUC.data = (ContactSearchResult.ContactSearchResultData)dataItem;
            aspxItem.Controls.Add(contactSearchResultUC);
        }
        else if (dataItem is NewsArticleSearchResult.NewsArticleSearchResultData)
        {
            var newsArticleSearchResultUC = LoadControl("~/UserControls/ResultsListingSearchResult/NewsArticleSearchResult.ascx") as ASP.NewsArticleSearchResult;
            newsArticleSearchResultUC.data = (NewsArticleSearchResult.NewsArticleSearchResultData)dataItem;
            aspxItem.Controls.Add(newsArticleSearchResultUC);
        }

        ...etc
Run Code Online (Sandbox Code Playgroud)