Repeater anidados

En aplicaciones web con ASP.NET es muy habitual el uso de controles del tipo Repeater, DataList, DataGrid… para mostrar listados de cualquier cosa. 

En el caso de querer listas de datos dentro de una lista de datos, como por ejemplo para mostrar listas maestro-detalle, listas categorizadas… se hace uso de estos controles anidados.

El siguiente es un caso sencillo de repeater anidados.

Desde la parte HTML se pueden configurar los campos que queremos mostrar, el encabezado, pie, item alternativos…, mientras que desde la clase podemos controlar los eventos, utilizar la información que nos llega desde el repeater para conseguir o mostrar otro tipo de datos…

No se puede acceder al repeater hijo directamente desde código, porque no existe un único control, sino que existirá uno por cada elemento del listado padre, que empezará a existir a partir de hacer el DataBind, en tiempo de ejecución. Para acceder a él habrá que hacerlo a través del evento OnItemDataBound, mediante la propiedad FindControl, que busca dentro de los controles del repeater padre.

Además de utilizar el FindControl, se hará un cast a Repeater, tras el cual ya se puede rellenar este control mediante DataSource y DataBind.

Con esto no encontramos directamente el repeater de la parte de HTML, sino que se genera otro repeater con ese mismo nombre y características en tiempo de ejecución dentro del repeater padre, uno por cada línea del repeater padre.

Para mostrar los datos en la parte HTML hemos utilizado ><%#Eval("Id") %>, aunque también se puede usar <%#Container.DataItem%> o DataBinder.Eval.

Parte HTML

  1. <asp:RepeaterID="rptEmpresas" runat="server" OnItemDataBound="rptEmpresas_ItemDataBound" OnItemCommand="rptEmpresas_ItemCommand">
  2.  
  3. <HeaderTemplate><table></HeaderTemplate>
  4.  
  5. <ItemTemplate>
  6.  
  7. <tr class="alternative">
  8.  
  9. <td>
  10.  
  11. <h2>Empresa</h2>
  12.  
  13. <div><span>Cif: </span><span><%# Eval("Id") %></span></div>
  14.  
  15. <div><span>Raz&oacute;n social: </span><span><%# Eval("RazonSocial")%></span></div>
  16.  
  17. </td>
  18.  
  19. </tr>
  20.  
  21. <tr>
  22.  
  23. <td>
  24.  
  25. <h3><asp:Label ID="lblAccionesFormativas" runat="server">Acciones formativas</asp:Label></h3>
  26.  
  27. <asp:Repeater ID="rptAccionesFormativas" runat="server">
  28.  
  29. <HeaderTemplate>
  30.  
  31.  
  32. <tr>
  33.  
  34. <th></th>
  35.  
  36. <th>C&oacute;digo</th>
  37.  
  38. </tr>
  39.  
  40. </HeaderTemplate>
  41.  
  42. <ItemTemplate>
  43.  
  44. <tr>
  45.  
  46. <td><asp:HiddenField runat="server" ID="accionFormativaId" Value='<%# Eval("Id")%>' /></td>
  47.  
  48. <td><span><%# Eval("Id")%></span></td>
  49.  
  50. </tr>
  51.  
  52. </ItemTemplate>
  53.  
  54. <AlternatingItemTemplate>
  55.  
  56. <tr class="alternative">
  57.  
  58. <td><asp:HiddenField runat="server" ID="accionFormativaId" Value='<%# Eval("Id")%>' /></td>
  59.  
  60. <td><span><%# Eval("Id")%></span></td>
  61.  
  62. </tr>
  63.  
  64. </AlternatingItemTemplate>
  65.  
  66. <FooterTemplate></table></FooterTemplate>
  67.  
  68. </asp:Repeater>
  69.  
  70. </td>
  71.  
  72. </tr>
  73.  
  74. <tr>
  75.  
  76. <td>
  77.  
  78. <asp:ButtonID="btnGuardar" runat="server" Text="Guardar" CommandName="Guardar" CommandArgument='<%# Eval("Id") %>'/>
  79.  
  80. <asp:Labelrunat="server" ID="lblCorrecto" CssClass="correct_message"></asp:Label>
  81.  
  82. <asp:Labelrunat="server" ID="lblError" CssClass="error_message"></asp:Label>
  83.  
  84. </td>
  85.  
  86. </tr>
  87.  
  88. </ItemTemplate>
  89.  
  90. <AlternatingItemTemplate>
  91.  
  92. <tr>
  93.  
  94. <td class="field_value">
  95.  
  96. <h2>Empresa</h2>
  97.  
  98. <div><span>Cif: </span><span><%# Eval("Id") %></span></div>
  99.  
  100. <div><span>Raz&oacute;n social: </span><span><%# Eval("RazonSocial")%></span></div>
  101.  
  102. </td>
  103.  
  104. </tr>
  105.  
  106. <tr>
  107.  
  108. <td>
  109.  
  110. <h3><asp:Label ID="lblAccionesFormativas" runat="server">Acciones formativas</asp:Label></h3>
  111.  
  112. <asp:Repeater ID="rptAccionesFormativas" runat="server">
  113.  
  114. <HeaderTemplate>
  115.  
  116.  
  117. <tr>
  118.  
  119. <th class="campo_oculto"></th>
  120.  
  121. <th>C&oacute;digo</th>
  122.  
  123. </tr>
  124.  
  125. </HeaderTemplate>
  126.  
  127. <ItemTemplate>
  128.  
  129. <tr>
  130.  
  131. <td><asp:HiddenField runat="server" ID="accionFormativaId" Value='<%# Eval("Id")%>' /></td>
  132.  
  133. <td><span><%# Eval("Id")%></span></td>
  134.  
  135. </tr>
  136.  
  137. </ItemTemplate>
  138.  
  139. <AlternatingItemTemplate>
  140.  
  141. <tr class="alternative">
  142.  
  143. <td><asp:HiddenField runat="server" ID="accionFormativaId" Value='<%# Eval("Id")%>' /></td>
  144.  
  145. <td><span><%# Eval("Id")%></span></td>
  146.  
  147. </tr>
  148.  
  149. </AlternatingItemTemplate>
  150.  
  151. <FooterTemplate></table></FooterTemplate>
  152.  
  153. </asp:Repeater>
  154.  
  155. </td>
  156.  
  157. </tr>
  158.  
  159. <tr>
  160.  
  161. <td>
  162.  
  163. <asp:ButtonID="btnGuardar" runat="server" Text="Guardar" CommandName="Guardar" CommandArgument='<%# Eval("Id") %>'/>
  164.  
  165. <asp:Labelrunat="server" ID="lblCorrecto" CssClass="correct_message"></asp:Label>
  166.  
  167. <asp:Labelrunat="server" ID="lblError" CssClass="error_message"></asp:Label>
  168.  
  169. </td>
  170.  
  171. </tr>
  172.  
  173. </AlternatingItemTemplate>
  174.  
  175. <FooterTemplate></table></FooterTemplate>
  176.  
  177. </asp:Repeater>

 

  1. <strong>Parte de la clase</strong>
  2.  
  3. //Se rellena el repeater padre mediante las propiedades DataSource y DataBind
  4.  
  5. protectedvoid MostrarEmpresasRLT()
  6.  
  7. {
  8.  
  9. Service service = new Service();
  10.  
  11. rptEmpresas.DataSource = service.GetEmpresasConRLT();
  12.  
  13. rptEmpresas.DataBind();
  14.  
  15. }

  En el evento ItemDataBound, se tiene acceso a los datos de cada item, por lo que si necesitamos acceder a algún dato dentro de una fila, éste es el sitio indicado.

  1. protectedvoid rptEmpresas_ItemDataBound(object sender, RepeaterItemEventArgs e)
  2.  
  3. {
  4.  
  5. if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
  6.  
  7. {
  8.  
  9. Service service = new Service();
  10.  
  11. //obtener la entidad de la fila del repeater padre
  12.  
  13. Empresa empresa = (Empresa)e.Item.DataItem;
  14.  
  15. Repeater rptAccionesFormativas = new Repeater();
  16.  
  17. rptAccionesFormativas = (Repeater)e.Item.FindControl("rptAccionesFormativas");
  18.  
  19. rptAccionesFormativas.DataSource = service.GetAccionesFormativasByEmpresaId(empresa.Id);
  20.  
  21. rptAccionesFormativas.DataBind();
  22.  
  23. //Cargar el label del t&iacute;tulo de acciones formativas
  24.  
  25. Label lblAccionesFormativas = new Label();
  26.  
  27. lblAccionesFormativas = (Label)e.Item.FindControl("lblAccionesFormativas");
  28.  
  29. if(rptAccionesFormativas.Items.Count > 0)
  30.  
  31. {
  32.  
  33. lblAccionesFormativas.Visible = true;
  34.  
  35. rptAccionesFormativas.Visible = true;
  36.  
  37. for (int i = 0; i < rptAccionesFormativas.Items.Count; i++)
  38.  
  39. {
  40.  
  41. //Cargar el desplegable
  42.  
  43. HiddenField accionFormativaId = (HiddenField)rptAccionesFormativas.Items[i].FindControl("accionFormativaId");
  44.  
  45. }
  46.  
  47. }
  48.  
  49. else
  50.  
  51. {
  52.  
  53. lblAccionesFormativas.Visible = false;
  54.  
  55. rptAccionesFormativas.Visible = false;
  56.  
  57. }
  58.  
  59. }
  60.  
  61. }
  62.  
  63. protectedvoid rptEmpresas_ItemCommand(object source, RepeaterCommandEventArgs e)
  64.  
  65. {
  66.  
  67. if (e.CommandName == "Guardar")
  68.  
  69. {
  70.  
  71. Service service = new Service();
  72.  
  73. Repeater rptAccionesFormativas = (Repeater)e.Item.FindControl("rptAccionesFormativas");
  74.  
  75. bool correcto = true;
  76.  
  77. Label lblCorrecto = (Label)e.Item.FindControl("lblCorrecto");
  78.  
  79. Label lblError = (Label)e.Item.FindControl("lblError");
  80.  
  81. try
  82.  
  83. {
  84.  
  85. service.ModificarEmpresa(e.CommandArgument.ToString());
  86.  
  87. for(int i = 0; i < rptAccionesFormativas.Items.Count; i++)
  88.  
  89. {
  90.  
  91. HiddenField accionFormativaId = (HiddenField)rptAccionesFormativas.Items[i].FindControl("accionFormativaId");
  92.  
  93. service.ModificarAccionFormativa(e.CommandArgument.ToString(), accionFormativaId.Value);
  94.  
  95. }
  96.  
  97. }
  98.  
  99. catch (Exception ex)
  100.  
  101. {
  102.  
  103. lblError.Text = ex.ToString();
  104.  
  105. correcto = false;
  106.  
  107. }
  108.  
  109. if (correcto)
  110.  
  111. {
  112.  
  113. lblCorrecto.Text = "Se ha modificado con &eacute;xito";
  114.  
  115. }
  116.  
  117. }
  118.  
  119. }