Toon posts:

[ASP.NET] Repeater in Repeater

Pagina: 1
Acties:

Verwijderd

Topicstarter
ik wil graag het volgende bereiken:

Ik heb een bepaalde category en daaronder ik ik dus de subcategorieen zetten.
Lijkt me makkelijk te gaan met repeater controls dacht ik.


Voorbeeld:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<asp:Repeater ID="rpCatagories" runat="server">
<HeaderTemplate><h1 class="subject">Categories.</h1></HeaderTemplate>
<ItemTemplate>
    <p class="subject"><a href="#"><%# Eval("Category") %></a></p>
                <asp:Repeater ID="rpSubCatagories" runat="server">
                <HeaderTemplate><h1 class="subject">SubCategories.</h1></HeaderTemplate>
                <ItemTemplate>
        <p class="subject"><a href="#"><%# Eval("SubCategory") %></a></p>
                </ItemTemplate>
                <FooterTemplate></FooterTemplate>
                </asp:Repeater>
</ItemTemplate>
<FooterTemplate></FooterTemplate>
</asp:Repeater>


category 1
SubCat1 SubCat2 SubCat3 SubCat4 etc.

Nu haal ik de category 1 binnen met een dataset en bind() die aan een repeater. Makkelijk. Maar nu probeer ik de subcategory ook te binden aan een repeater en die dan vervolgens in de <ItemTemplate> te plaatsen. Dit laatste lijkt me niet te lukken.

Is dit wel de juiste aanpak of kan het beter op een andere manier.

Graag jullie menig of adviezen.

  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

(jarig!)
Het is een tikje lastig aangezien de ID van de Repeater in het ItemTemplate niet bekend is bij compile time en je zult dus de Repeater dynamisch moeten databinden.
Ik heb (in VS2005/.Net 2.0 welliswaar) het volgende gefixt, 1 aspx pagina met daarop een Repeater control en in het ItemTemplate daarvan een nieuwe Repeater _zonder_ ID.
HTML:
1
2
3
4
5
6
7
8
9
10
11
<asp:Repeater ID="Repeater1" runat="server">
        <HeaderTemplate>TOP LEVEL</HeaderTemplate>
        <FooterTemplate>END TOP LEVEL</FooterTemplate>
        <ItemTemplate>
            <asp:Repeater runat="server">
                <HeaderTemplate>SUB LEVEL</HeaderTemplate>
                <FooterTemplate>END SUB LEVEL</FooterTemplate>
                <ItemTemplate><%# DataBinder.GetDataItem(Container) %></ItemTemplate>
            </asp:Repeater>
        </ItemTemplate>
</asp:Repeater>

In de code behind heb ik 3 arraylists gedefinieerd, 1 voor de top-level en 2 voor de sub-levels. De sub-levels zijn de children van de top-level arraylist.
Om de dynamische Repeaters te vullen heb ik een handler aan het ItemCreated event gehangen. In die handler wordt gekeken naar de ItemIndex. Deze index moet groter zijn dan -1 (header en footer). Via deze index kun je dan de goeie sub-level arraylist uit de top-level halen (zelfde index als de dynamische Repeater dus).
Class met de arraylists
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public ArrayList toplevel = new ArrayList();
public ArrayList sublevel1 = new ArrayList();
public ArrayList sublevel2 = new ArrayList();

protected void Page_Load(object sender, EventArgs e)
{
    sublevel1.Add("one");
    sublevel1.Add("two");
    sublevel1.Add("three");
    sublevel1.Add("four");

    sublevel2.Add("five");
    sublevel2.Add("six");
    sublevel2.Add("seven");
    sublevel2.Add("eight");

    toplevel.Add(sublevel1);
    toplevel.Add(sublevel2);

    this.Repeater1.DataSource = toplevel;
    this.Repeater1.ItemCreated += new RepeaterItemEventHandler(HandleRepeaterItemCreated);
    this.Repeater1.DataBind();
}

ItemCreated event handler
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public void HandleRepeaterItemCreated(object sender, RepeaterItemEventArgs args)
{
    RepeaterItem item = args.Item;
    if (item.ItemIndex < 0)
    {
        return;
    }
    foreach (Control c in item.Controls)
    {
        if (c is Repeater)
        {
            Repeater r = (Repeater)c;
            r.DataSource = this.toplevel[item.ItemIndex];
            r.DataBind();
        }
    }
}

Mocht je de solution willen hebben moet je maar even mailen (zie profiel)

Nu met Land Rover Series 3 en Defender 90


Verwijderd

Topicstarter
okee, ik heb dit dus geprobeerd maar krijg een error melding.
Ik gebruik als DataSource wel een dataSet, maar dat mag lijkt mij niet uitmaken.

.aspx
C#:
1
2
3
4
5
6
7
8
9
10
11
12
<asp:Repeater ID="repeaterSnippetCatagories" runat="server">
<HeaderTemplate><h1 class="subject">Snippet Categories.</h1></HeaderTemplate>
<ItemTemplate>
    <p class="subject"><a href="#"><%# Eval("SnippetCategory") %></a></p>
    <asp:Repeater runat="server">
    <HeaderTemplate></HeaderTemplate>                       
    <ItemTemplate><%# Eval("SnippetSubCategory") %></ItemTemplate>
    <FooterTemplate></FooterTemplate>
    </asp:Repeater>
</ItemTemplate>
<FooterTemplate></FooterTemplate>
</asp:Repeater>


.cs
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void repeaterSnippetCatagories_ItemCreated(object sender, RepeaterItemEventArgs e)
{
    RepeaterItem item = e.Item;
    if (item.ItemIndex < 0)
    {
        return;
    }
    foreach (Control c in item.Controls)
    {
        if (c is Repeater)
        {
            Repeater r = (Repeater)c;
            r.DataSource = SnippetHandlers.GetAllSnippedSubCategories(1);
            r.DataBind();
        }
    } 
}


Exception Message:
System.InvalidOperationException was unhandled by user code
Message="Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control."

  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

(jarig!)
Probeer eens ipv Eval("SnippetSubCategory") DataBinder.Eval(Container,"SnippetSubCategory") misschien dat dat wel werkt

Nu met Land Rover Series 3 en Defender 90


Verwijderd

Topicstarter
Toppie.

Nu werkt het wel .... :)
Als was het met DataBinder.Eval(Container.DataItem, "SnippetSubCategory")
Waarom werkt het wel bij de "buitenste" repeater met alleen Eval().

  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

(jarig!)
Het heeft waarschijnlijk iets met scope te maken maar dat weet ik niet zeker.

Nu met Land Rover Series 3 en Defender 90


  • wasigh
  • Registratie: Januari 2001
  • Niet online

wasigh

wasigh.blogspot.com

Overigens vind ik beter de onItemDataBound event gebruiken. Dan scheid je tenminste je HTML van je ASP.NET code en heb je geen lelijke ><%# DataBinder.GetDataItem(Container) %> in je HTML.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
       void R1_ItemDataBound(Object Sender, RepeaterItemEventArgs e) {
                              
          // This event is raised for the header, the footer, separators, and items.

          // Execute the following logic for Items and Alternating Items.
          if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) {
                 
             if (((Evaluation)e.Item.DataItem).Rating == "Good") {
                ((Label)e.Item.FindControl("RatingLabel")).Text= "<b>***Good***</b>";
             }
          }
       

In je event kun je dan met FindControl() je controls in je template opvragen. Zie ook: http://msdn.microsoft.com...sonitemdataboundtopic.asp

[ Voor 4% gewijzigd door wasigh op 08-11-2005 09:12 ]


Verwijderd

Topicstarter
Op dit moment werkt het allemaal prima
ik ga dat artikel even doornemen en nog meer lezen over repeaters, Nested repeaters en Databinding.
Ik ben er ondertussen ook achter dat je bij de

ItemCreated(object sender, RepeaterItemEventArgs e)

ook

int i = Convert.ToInt32(DataBinder.Eval(e.Item.DataItem, "CatID"));

kan doen.
Dat heeft me ook even wat tijd gekost, maar is super handing met subcategories.

Normaal werk ik met Windows Forms ipv web forms, dus ik moet even wennen aan de overstap :)

bedankt voor de reacties, ik ben een stuk veder gekomen.
Pagina: 1