代码之家  ›  专栏  ›  技术社区  ›  Jaimin Soni Rajeev Ranjan

如何在asp.net中实现N级嵌套Repeater控件?

  •  1
  • Jaimin Soni Rajeev Ranjan  · 技术社区  · 11 年前

    我想在asp.net中使用中继器控制实现n级数据层次结构。 有什么解决方案可以实现这种层次结构吗?

    2 回复  |  直到 11 年前
        1
  •  2
  •   Menno van den Heuvel    11 年前

    对于这个答案,我建议以编程方式创建模板-请参见此处: https://msdn.microsoft.com/en-us/library/aa289501 . 可能有一些方法可以使用标记中创建的模板,但这似乎更容易,而且肯定更灵活。

    我从一个只有中继器(而不是模板)的页面开始

    <body>
        <form id="form1" runat="server">
        <div>
            <asp:Repeater runat="server" ID="TestRepeater">
            </asp:Repeater>
        </div>
        </form>     
    </body>
    

    和一个数据类

    public class DataClass
    {
        public string Name { get; set; }
        public List<DataClass> Children { get; set; }
    }
    

    对于模板,我们使用以下类:

    public class DataTemplate : ITemplate
    {
        public void InstantiateIn(Control container)
        {
            var name = new Literal();
            var repeater = new Repeater();
    
            name.DataBinding += BindingLiteral;
            repeater.DataBinding += BindingRepeater;
    
            // this here makes it recursive
            repeater.ItemTemplate = new DataTemplate();
    
            container.Controls.Add(name);
            container.Controls.Add(repeater);
        }
    
        private void BindingLiteral(object sender, System.EventArgs e)
        {
            var name = (Literal)sender;
            var container = (RepeaterItem)name.NamingContainer;
            name.Text = String.Concat("<h2>", DataBinder.Eval(container.DataItem, "Name").ToString(), "</h2>");
        }
    
        private void BindingRepeater(object sender, System.EventArgs e)
        {
            var name = (Repeater)sender;
            var container = (RepeaterItem)name.NamingContainer;
            name.DataSource = DataBinder.Eval(container.DataItem, "Children");
        }
    }
    

    显然,您需要使用更复杂的模板。请注意,如果您当前在标记中有一个模板,您可以简单地使用标记解析器生成的代码,并根据您的需要调整它。

    现在,在页面后面的代码中,我们简单地分配ItemTemplate和DataSource:

    public partial class Test : System.Web.UI.Page
    {
        protected void Page_Init(object sender, EventArgs e)
        {
            TestRepeater.DataSource = GetTestData();
            TestRepeater.ItemTemplate = new DataTemplate();
            TestRepeater.DataBind();
        }
    }
    

    这很好,因为你的模板只是一个类,所以你可以添加一个 public Int32 Depth { get; set; } 并根据您的深度更改生成的控件。

        2
  •  1
  •   Jereck    8 年前

    另一种解决方案,无需以编程方式创建模板:

    使用简单的数据类:

    public class DataClass
    {
        public string Name { get; set; }
        public List<DataClass> Children { get; set; }
    }
    

    在ASPX标记中创建父中继器,将项目显示代码放入ItemTemplate中,然后添加第二个“空”中继器:

    <body>
        <form id="form1" runat="server">
        <div>
            <asp:Repeater runat="server" ID="ParentRepeater" OnItemDataBound="Repeater_ItemDataBound">
                <ItemTemplate>
                    <asp:Literal runat="server" Text="<%# Eval("Name") %>"></asp:Literal>
                    <asp:Repeater runat="server" ID="ChildRepeater" OnItemDataBound="Repeater_ItemDataBound" Visible="false">
                    </asp:Repeater>
                </ItemTemplate>
            </asp:Repeater>
        </div>
        </form>     
    </body>
    

    在后面的代码中:

    protected void Repeater_ItemDataBound(object sender, RepeaterItemEventArgs e) {
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) {
            DataClass currentItem = (DataClass)e.Item.DataItem;
    
            if (currentItem.Children.Count > 0) {
                Repeater ChildRepeater = (Repeater)e.Item.FindControl("ChildRepeater");
    
                ChildRepeater.DataSource = currentItem.Children;
                ChildRepeater.ItemTemplate = ParentRepeater.ItemTemplate;
                ChildRepeater.Visible = true;
                ChildRepeater.DataBind();
            }
        }
    }
    
    推荐文章