我如何在asp:Repeater中更改我的ItemTemplate? [英] How do I vary my ItemTemplate inside an asp:Repeater?

查看:36
本文介绍了我如何在asp:Repeater中更改我的ItemTemplate?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用于显示搜索结果的用户控件.显示的每个结果的HTML会根据显示的结果类型而有所不同:以一种方式显示联系人",以另一种方式显示新闻文章",依此类推.大约有10种不同类型的结果都被标记他们使用HTML的方式有所不同-—因此我需要大约10个左右的模板来显示各个结果,可以根据显示的当前项目在这些模板之间进行选择.

I have a user control which is used to display search results. The HTML for each result displayed will vary based on the type of result being displayed: "contacts" are displayed in one way, "news articles" are displayed in another, etc. There are around 10 different types of results that are all marked up differently when they get to HTML — so I need around 10 or so different templates for individual results that I can choose between based on the current item being displayed.

我正在使用 asp:Repeater 显示结果,但是我不知道如何在 asp:Repeater< ItemTemplate> 中选择合适的模板>.理想情况下,我希望ASP根据通过 searchResultsRepeater.DataSource —传递的对象类型来选择要使用的适当模板.但是很遗憾,我无法使用打开类型(请参见此C#博客条目的打开类型为).但是,我只能通过一个枚举值来显示要显示的结果类型.

I'm using an asp:Repeater to display the results, but I don't know how to select the appropriate template within the asp:Repeater <ItemTemplate>. Ideally I'd like the ASP to select the appropriate template to use based upon the object type being passed in via the searchResultsRepeater.DataSource — but unfortunately I can't use switch on type (see this blog entry for C# switch on type). I can however just pass through an enum value for the type of result being displayed.

在后端C#代码中,我有一个抽象的内联 SearchResult 类,以及该类的子类,例如 ContactSearchResult NewsArticleSearchResult 等.然后,将 searchResultsRepeater.DataSource 绑定到 List< SearchResult> .每个 SearchResult 都包含一个 ResultListingType type 字段,该字段提供了要显示的列表的类型.

In the backend C# code I have an abstract inline SearchResult class, and children of that class like ContactSearchResult, NewsArticleSearchResult, etc. The searchResultsRepeater.DataSource would then be bound to a List<SearchResult>. Each SearchResult contains a ResultListingType type field which gives the type of the listing to be displayed.

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

My first attempt was something like this:

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

不幸的是,这不起作用:

Unfortunately, this doesn't work:

    <%#...%> 括号内,
  • "switch"和"if"都给出无效的表达式项".
  • "Container.DataItem"在<%...%> 方括号内给出名称""Container"在当前上下文中不存在".
  • "switch" and "if" both give "invalid expression term" inside the <%# ... %> brackets.
  • "Container.DataItem" gives "the name "Container" does not exist in the current context" inside <% ... %> brackets.

如何更改asp:repeater中使用的ItemTemplate上,我发现了一些有用的东西..然后我尝试了类似的东西:

I found something that looked useful at how to change the ItemTemplate used in an asp:repeater?. I then tried something like:

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

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

In my ItemDataBound event I did:

        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");
        }

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

Unfortunately this doesn't work because ASP seems to still be running the contents of the PlaceHolder even after I set Visible = false. I get the error "DataBinding: 'usercontrols_ResultsListing+ContactResultsListing' does not contain a property with the name 'newsHeadline'" — i.e. the newsResultListing PlaceHolder is still looking for the "newsHeadline" field, even though that field doesn't exist for the result listing type being displayed.

事实上,我已经尝试过快速测试,将 New Exception("e"); 放入ItemDataBound中,并且看起来甚至在控制流到达之前就抛出了"DataBinding"错误.ItemDataBound方法,因此实际上我无法做任何事情来避免此错误.

In fact I've tried a quick test throw new Exception("e"); in my ItemDataBound, and it looks like the "DataBinding" error is thrown even before control flow gets to the ItemDataBound method, so there's really nothing I can do in there to avoid this error.

我想我可以将每个字段都添加到父类中,而在我的孩子中将大多数字段保留为null,但这看起来确实很丑.

I suppose I could add every single field to the parent class and leave most of them null in my children, but that seems really ugly.

是否有一种方法可以使此工作有效,或者有一种更容易的方法根据我当前正在遍历的Container.DataItem的类型来更改我的ItemTemplate?我对ASP非常陌生,因此可能缺少一些简单的东西.:)

Is there a way to make this work, or an easier way to vary my ItemTemplate based upon the type of Container.DataItem I'm currently iterating over? I'm very new to ASP so there's likely something simple that I've missed. :)

推荐答案

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

OK, I think I've found a solution — I've created multiple additional user controls, one for each type of search result. Each one of these controls defines the HTML template for its corresponding type of search result.

我的 asp:Repeater ItemTemplate 中绝对没有包含任何内容:

My asp:Repeater contains absolutely nothing inside its ItemTemplate:

    <asp:Repeater ID="searchResultsRepeater" runat="server">
        <ItemTemplate>
            <%-- empty template: we insert usercontrols in the ItemDataBound --%>
        </ItemTemplate>
    </asp:Repeater>

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

I bind a List<SearchResultData> to my asp:Repeater as before, and as before this list contains more specific subtypes of SearchResultData based on the type of result to be shown.

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

In my ItemDataBound handler I instantiate one of those user controls based on the type of data in e.Item.DataItem and then insert that user control into the repeater:

        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

这篇关于我如何在asp:Repeater中更改我的ItemTemplate?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆