Repeater内Accordion控件数据绑定无显示问题求助
解决Repeater嵌套Accordion时内部数据绑定失效的问题
哥们,你遇到的这个问题其实很常见——Accordion内部的Container.DataItem上下文和Repeater的不是一回事!
在Repeater的ItemTemplate里,直接写<%# DataBinder.Eval(Container.DataItem,"strTitle") %>能正常显示,是因为这里的Container指的是RepeaterItem,它的DataItem就是你绑定给Repeater的当前项数据。但到了Accordion的Pane里,Container变成了AccordionPane的容器,它根本没有Repeater的DataItem,所以绑定自然就空了。
下面给你三种实用的解决方案:
方案一:通过NamingContainer向上找Repeater的上下文
你可以通过Container.NamingContainer逐层向上获取父容器,直到拿到Repeater的RepeaterItem:
<asp:Repeater runat="server" ID="rptMain"> <HeaderTemplate> Stuff </HeaderTemplate> <ItemTemplate> <%# DataBinder.Eval(Container.DataItem,"strTitle") %> <ajax:Accordion ID="acdClass" runat="server" FadeTransitions="true" AutoSize="None" RequireOpenedPane="false" SelectedIndex="-1"> <Panes> <ajax:AccordionPane ID="panTitle1" runat="server"> <Header> Accrdion Header - <%# DataBinder.Eval(Container.NamingContainer.NamingContainer.DataItem, "strTitle") %> </Header> <Content> Content Info - <%# DataBinder.Eval(Container.NamingContainer.NamingContainer.DataItem, "strTitle") %> </Content> </ajax:AccordionPane> </Panes> </ajax:Accordion> </ItemTemplate> </asp:Repeater>
为什么是两层NamingContainer?
- 第一层
Container.NamingContainer:AccordionPane的父容器是Accordion - 第二层
Container.NamingContainer.NamingContainer:Accordion的父容器是RepeaterItem,这才是拥有你需要的DataItem的容器
方案二:在ItemTemplate里提前缓存DataItem变量
这种方法更直观,避免多层NamingContainer的嵌套:
<asp:Repeater runat="server" ID="rptMain"> <HeaderTemplate> Stuff </HeaderTemplate> <ItemTemplate> <%-- 先把Repeater的DataItem存到变量里 --%> <%# var currentItem = Container.DataItem; %> <%# DataBinder.Eval(currentItem,"strTitle") %> <ajax:Accordion ID="acdClass" runat="server" FadeTransitions="true" AutoSize="None" RequireOpenedPane="false" SelectedIndex="-1"> <Panes> <ajax:AccordionPane ID="panTitle1" runat="server"> <Header> Accrdion Header - <%# DataBinder.Eval(currentItem, "strTitle") %> </Header> <Content> Content Info - <%# DataBinder.Eval(currentItem, "strTitle") %> </Content> </ajax:AccordionPane> </Panes> </ajax:Accordion> </ItemTemplate> </asp:Repeater>
这样在Accordion内部直接用currentItem就能访问到Repeater当前项的数据,代码可读性更高。
方案三:后台代码绑定(更灵活的方式)
如果以后Accordion需要绑定更复杂的数据,或者你想把绑定逻辑放到后台,推荐用Repeater的ItemDataBound事件:
第一步:给Repeater添加ItemDataBound事件
<asp:Repeater runat="server" ID="rptMain" OnItemDataBound="rptMain_ItemDataBound"> <HeaderTemplate> Stuff </HeaderTemplate> <ItemTemplate> <%# DataBinder.Eval(Container.DataItem,"strTitle") %> <ajax:Accordion ID="acdClass" runat="server" FadeTransitions="true" AutoSize="None" RequireOpenedPane="false" SelectedIndex="-1"> <Panes> <ajax:AccordionPane ID="panTitle1" runat="server"> <Header></Header> <Content></Content> </ajax:AccordionPane> </Panes> </ajax:Accordion> </ItemTemplate> </asp:Repeater>
第二步:后台实现绑定逻辑
protected void rptMain_ItemDataBound(object sender, RepeaterItemEventArgs e) { // 只处理数据项(忽略Header、Footer等) if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { // 获取当前Repeater项的数据 var dataItem = e.Item.DataItem; // 找到Accordion控件 var acdClass = (Accordion)e.Item.FindControl("acdClass"); // 找到AccordionPane var panTitle1 = (AccordionPane)acdClass.FindControl("panTitle1"); // 给Header和Content赋值 panTitle1.HeaderContainer.Controls.Add(new LiteralControl($"Accrdion Header - {DataBinder.Eval(dataItem, "strTitle")}")); panTitle1.ContentContainer.Controls.Add(new LiteralControl($"Content Info - {DataBinder.Eval(dataItem, "strTitle")}")); } }
这种方法的好处是,你可以在后台做更多逻辑处理,比如判断数据是否为空,或者给Accordion绑定独立的数据源(如果需要的话)。
内容的提问来源于stack exchange,提问作者Wade Gregory Tripp
相关产品推荐
相关产品推荐

