2011-05-30 20 views
7

Necesito saber cómo anidar repetidores dentro de un control de usuario. El lado html de las cosas está bien, es el enlace y el código detrás del que necesito ayuda. Solo he podido encontrar ejemplos usando una fuente de datos SQL, lo que realmente no ayuda.Cómo anidar repetidores en asp.net

Mis repetidores este aspecto:

<asp:Panel ID="pnlDiscipline" runat="server" CssClass=""> 
    <asp:Repeater ID="rptDiscipline" runat="server"> 
     <ItemTemplate> 
      <h4><%#Eval("Discipline")%></h4> 
      <ul> 
       <asp:Repeater ID="rptPrograms" runat="server"> 
        <ItemTemplate> 
         <li><asp:HyperLink runat="server" Text='<%#Eval("Name") %>' NavigateUrl='<%#Eval("Link") %>'></asp:HyperLink> <%#Eval ("Notation") %></li> 
        </ItemTemplate> 
       </asp:Repeater> 
      </ul> 
     </ItemTemplate> 
    </asp:Repeater> 

Lo que tengo que hacer es de esperar razonablemente claro - la disciplina h4 debe aparecer una vez, todas las entradas que pertenecen a la disciplina se enumeran a continuación, luego el siguiente h4, luego la lista apropiada, el siguiente h4 y así sucesivamente.

La fuente de datos es una vista de datos creada en el código subyacente donde cada fila tiene 'Nombre', 'Enlace', 'NOtation' y 'Disciplina'. He vinculado la vista de datos al repetidor externo y se comporta como se esperaba - enumera el nombre de la disciplina para cada entrada, pero no muestra los datos en el repetidor interno

¿Cómo hago para hacer este trabajo

EDIT:.? solo para aclarar, tengo una tabla de datos en el código subyacente cada fila. en esa tabla hay un elemento, cada elemento pertenece a una disciplina. Quiero usar el repetidor externo para enumerar las disciplinas, el interno para enumerar los elementos agrupados en cada disciplina. Como ese:

<h4>DISCIPLINE 1</h4> 
    <ul> 
     <li>Item</li> 
     <li>Item</li> 
     <li>Item</li> 
    </ul> 
<h4>DISCIPLINE 2</h4> 
    <ul>   
     <li>Item</li>    
     <li>Item</li> 
    </ul> 
<h4>DISCIPLINE 3</h4> 
    <ul>   
     <li>Item</li>    
     <li>Item</li> 
    </ul> 

En la actualidad, la unión de la tabla de datos para el repetidor exterior da este (ejemplo utiliza los datos anteriores):

<h4>DISCIPLINE 1</h4> 
    <h4>DISCIPLINE 1</h4> 
    <h4>DISCIPLINE 1</h4> 
    <h4>DISCIPLINE 2</h4> 
    <h4>DISCIPLINE 2</h4> 
    <h4>DISCIPLINE 3</h4> 
    <h4>DISCIPLINE 3</h4> 

he utilizado OnItemDataBound en el repetidor exterior como se sugiere, y como un caso de prueba soy capaz de acceder a los datos:

protected void rptDiscipline_ItemDataBound(Object Sender, RepeaterItemEventArgs e) 
{ 
    DataRowView drView = (DataRowView) e.Item.DataItem; 
    string name = drView["Name"] as string; 
    string link = drView["Link"] as string; 
    string notation = drView["Notation"] as string; 
    Response.Write(name + link + notation + "<br />") 
} 

Así que los datos están ahí, es exactamente lo que esperaría ver, simplemente no puedo conseguirlo ligado al repetidor interno. Si hay una forma más eficiente de lograr lo mismo, me complace volver a trabajar mi solución.

+0

puede obtener idea de este hilo http://stackoverflow.com/questions/1220715/creating-a-nested-repeater-control-dynamically/1220836#1220836 –

+0

lo que estás tratando de enlazar con el interior ¿reloj de repetición? tal vez publique la clase que está vinculando al repetidor externo. – EdmundYeung99

+0

@ Edmund: edité mi pregunta, espero que aclare mi problema – Nathan

Respuesta

7

En el mando exterior, utilizar el evento ItemDataBound, como este:

<asp:Repeater ID="rptDiscipline" runat="server" 
    OnItemDataBound="rptDiscipline_ItemDataBound"> 
... 

Luego, en el código subyacente, controlar el evento rptDiscipline_ItemDataBound y se unen manualmente el repetidor interior. El evento ItemDataBound del repetidor se dispara una vez por cada elemento que se repite. Así que harás algo como esto:

protected void rptDiscipline_ItemDataBound(Object Sender, RepeaterItemEventArgs e) 
{ 
    // To get your data item, cast e.Item.DataItem to 
    // whatever you're using for the data object; for example a DataRow. 

    // Get the inner repeater: 
    Repeater rptPrograms = (Repeater) e.Item.FindControl("rptPrograms"); 

    // Set the inner repeater's datasource to whatever it needs to be. 
    rptPrograms.DataSource = ... 
    rptPrograms.DataMember = ... 
    rptPrograms.DataBind(); 
} 

EDITAR: Actualizado para que coincida con la actualización de tu pregunta.

Debe vincular el repetidor externo a una fuente de datos que tenga solo un registro por cada elemento que desee que muestre el repetidor. Eso significa que la fuente de datos debe ser una colección/lista/tabla de datos/etc que solo tenga las disciplinas en ella. En su caso, recomendaría obtener List<string> de disciplinas del DataTable para la colección interna, y vincular el repetidor externo a eso. Luego, el repetidor interno se une a un subconjunto de los datos en la DataTable, utilizando el evento ItemDataBound. Para obtener el subconjunto, filtra la DataTable a través de un DataView.

Aquí está el código:

protected void Page_Load(object sender, EventItems e) 
{ 
    // get your data table 
    DataTable table = ... 

    if (!IsPostBack) 
    { 
     // get a distinct list of disciplines 
     List<string> disciplines = new List<string>(); 
     foreach (DataRow row in table) 
     { 
      string discipline = (string) row["Discipline"]; 
      if (!disciplines.Contains(discipline)) 
       disciplines.Add(discipline); 
     } 
     disciplines.Sort(); 

     // Bind the outer repeater 
     rptDiscipline.DataSource = disciplines; 
     rptDiscipline.DataBind(); 
    } 
} 

protected void rptDiscipline_ItemDataBound(Object Sender, RepeaterItemEventArgs e) 
{ 
    // To get your data item, cast e.Item.DataItem to 
    // whatever you're using for the data object 
    string discipline = (string) e.Item.DataItem; 

    // Get the inner repeater: 
    Repeater rptPrograms = (Repeater) e.Item.FindControl("rptPrograms"); 

    // Create a filtered view of the data that shows only 
    // the disciplines needed for this row 
    // table is the datatable that was originally bound to the outer repeater 
    DataView dv = new DataView(table); 
    dv.RowFilter = String.Format("Discipline = '{0}'", discipline); 

    // Set the inner repeater's datasource to whatever it needs to be. 
    rptPrograms.DataSource = dv; 
    rptPrograms.DataBind(); 
} 
+1

¿Se puede hacer configurando DataSource en el repetidor interno? – Nathan

+0

Hola @charlie: entiendo lo que quieres decir, pero no puedo hacer que funcione. ¿Puedes dar más detalles sobre tu respuesta? – Nathan

+0

@Nathan - Sí, puede, vea la respuesta de @lomaxx – Venemo

4

Si no desea hacerlo en el caso ItemDataBound, también puede hacerlo en línea en su página mediante la unión a una propiedad hijo del elemento padre si el niño la propiedad es una colección de este modo:

<asp:Repeater runat="server" ID="OuterRepeater" > 
    <ItemTemplate> 
     Outer Content: <%# DataBinder.Eval(Container.DataItem, "ParentProperty")%> 
     <asp:Repeater runat="server" ID="InnerRepeater" DataSource='<%# DataBinder.Eval(Container.DataItem, "ChildCollection")%>' > 
      <ItemTemplate> 
       <%# DataBinder.Eval(Container.DataItem, "ChildProperty")%> 
      </ItemTemplate> 
     </asp:Repeater> 
    </ItemTemplate> 
</asp:Repeater> 
1

primero tendrá dos listas, la lista de disciplinas, a continuación, la lista de todos sus datos.

Datos enlazan la lista de disciplinas al repetidor externo. Si hay 6 disciplinas, el repetidor debe repetir 6 veces.

<asp:Repeater ID="rptDiscipline" runat="server" OnItemDataBound="rptDiscipline_ItemDataBound"> 
     <ItemTemplate> 
      <h4><%# Eval("Discipline")%></h4> 
      <ul> 
       <asp:Repeater runat="server" ID="InnerRepeater" > 
        <ItemTemplate> 
         <li> 
          <asp:Label runat="server" ID="lbl" /> 
         </li> 
        </ItemTemplate> 
       </asp:Repeater> 
      </ul> 
     </ItemTemplate> 
    </asp:Repeater> 

protected void rptDiscipline_ItemDataBound(Object Sender, RepeaterItemEventArgs e) 
{  

    Repeater inner= (Repeater) e.Item.FindControl("InnerRepeater"); 

    //You want to bind all the data related to this discipline 
    DataRowView drView = (DataRowView) e.Item.DataItem; 
    string discipline= drView["Discipline"] as string; 

    //filter your total data with ones that match the discipline 

    inner.DataSource = //data bind the filtered list here 
    inner.DataBind(); 
} 
+0

No me preocupa cómo lo logre, pensé que anidar sería una solución, si no, eso está bien para mí. Su ejemplo no produce el resultado que estoy buscando. Necesito una lista de "nombre" agrupados por disciplina. Hay 150 filas en la tabla de datos, cada una con un nombre único y una de las seis disciplinas. – Nathan

+0

Creo que entiendo su problema ahora ... He publicado un código psudo – EdmundYeung99

Cuestiones relacionadas