2011-04-26 20 views
7
<asp:Button onclick="Some_event" Text="Add TextBox" ID="id1" runat="server" /> 
//once clicked: 
<asp:TextBox ID="txt1" ......></asp:TextBox> 
//when clicked again: 
<asp:TextBox ID="txt1" ......></asp:TextBox> 
<asp:TextBox ID="txt2" ......></asp:TextBox> 
//and so on... 

¿Existe alguna manera de crear controles dinámicos que persistan incluso después de la devolución de datos? En otras palabras, cuando el usuario hace clic en el botón, se generará un nuevo cuadro de texto y cuando vuelva a hacer clic, el primero permanecerá y se generará el segundo. ¿Cómo puedo hacer esto usando asp.net? Sé que si puedo crear los controles en el evento page_init, persistirán, pero no sé si será posible hacer clic en un botón antes de que ocurra la página_init, por lo tanto, debe haber otra forma.Control dinámico persistente en ASP.Net

+0

Los controles * deben * volver a crearse en la devolución de datos. Sin embargo, hay algunos proyectos para automatizar esta tarea, como [DynamicControlPlaceholder] (http://www.denisbauer.com/ASPNETControls/DynamicControlsPlaceholder.aspx) (persiste y luego vuelve a crear los controles). –

+0

sí, he leído sobre esto, pero me gustaría aprender esto :) – Shaokan

Respuesta

4

Sí, esto es posible. Una forma de hacer esto usando puramente ASP.NET (que parece lo que está pidiendo) sería mantener un recuento de los controles TextBox que ha agregado (almacenando ese valor en el ViewState) y recrear los controles TextBox en el Page_Load evento. Por supuesto, hoy en día la mayoría de la gente probablemente usarían Javascript o jQuery para manejar este lado del cliente tarea, pero armar un ejemplo rápido para demostrar cómo funciona con las devoluciones de datos:

portada:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="DynamicControls.aspx.cs" Inherits="MyAspnetApp.DynamicControls" EnableViewState="true" %> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head runat="server"></head> 
<body> 
    <form id="form1" runat="server"> 
    <div> 
     <asp:Button ID="btnAddTextBox" runat="server" Text="Add" OnClick="btnAddTextBox_Click" /> 
     <asp:Button ID="btnWriteValues" runat="server" Text="Write" OnClick="btnWriteValues_Click" /> 
     <asp:PlaceHolder ID="phControls" runat="server" /> 
    </div> 
    </form> 
</body> 
</html> 

Código detrás :

using System; 
using System.Web.UI.WebControls; 

namespace MyAspnetApp 
{ 
    public partial class DynamicControls : System.Web.UI.Page 
    { 
     protected void Page_Load(object sender, EventArgs e) 
     { 
      //Recreate textbox controls 
      if(Page.IsPostBack) 
      { 
       for (var i = 0; i < TextBoxCount; i++) 
        AddTextBox(i); 
      } 
     } 

     private int TextBoxCount 
     { 
      get 
      { 
       var count = ViewState["txtBoxCount"]; 
       return (count == null) ? 0 : (int) count; 
      } 
      set { ViewState["txtBoxCount"] = value; } 
     } 

     private void AddTextBox(int index) 
     { 
      var txt = new TextBox {ID = string.Concat("txtDynamic", index)}; 
      txt.Style.Add("display", "block"); 
      phControls.Controls.Add(txt); 
     } 

     protected void btnAddTextBox_Click(object sender, EventArgs e) 
     { 
      AddTextBox(TextBoxCount); 
      TextBoxCount++; 
     } 

     protected void btnWriteValues_Click(object sender, EventArgs e) 
     { 
      foreach(var control in phControls.Controls) 
      { 
       var textBox = control as TextBox; 
       if (textBox == null) continue; 
       Response.Write(string.Concat(textBox.Text, "<br />")); 
      } 
     } 
    } 
} 

Puesto que usted está volviendo a crear los controles en cada devolución de datos, los valores introducidos en los cuadros de texto se conservará a través de cada devolución de datos. Agregué btnWriteValues_Click para demostrar rápidamente cómo leer los valores de los cuadros de texto.

EDITAR
He actualizado el ejemplo añadir un panel que contiene un cuadro de texto y un botón Quitar. El truco aquí es que el botón Eliminar no elimina el Panel contenedor, simplemente hace que no sea Visible. Esto se hace para que todos los ID de control permanezcan iguales, por lo que los datos ingresados ​​permanecen con cada cuadro de texto. Si tuviéramos que eliminar el TextBox por completo, los datos después del TextBox que se eliminó cambiarían un TextBox en la siguiente devolución (solo para explicar esto un poco más claro, si tenemos txt1, txt2 y txt3, y eliminamos txt2, en la siguiente devolución de datos crearemos dos cuadros de texto, txt1 y txt2, y se perderá el valor que estaba en txt3).

public partial class DynamicControls : System.Web.UI.Page 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     if (Page.IsPostBack) 
     { 
      for (var i = 0; i < TextBoxCount; i++) 
       AddTextBox(i); 
     } 
    } 

    protected void btnAddTextBox_Click(object sender, EventArgs e) 
    { 
     AddTextBox(TextBoxCount); 
     TextBoxCount++; 
    } 

    protected void btnWriteValues_Click(object sender, EventArgs e) 
    { 
     foreach(var control in phControls.Controls) 
     { 
      var panel = control as Panel; 
      if (panel == null || !panel.Visible) continue; 
      foreach (var control2 in panel.Controls) 
      { 
       var textBox = control2 as TextBox; 
       if (textBox == null) continue; 
       Response.Write(string.Concat(textBox.Text, "<br />")); 
      } 
     } 
    } 

    private int TextBoxCount 
    { 
     get 
     { 
      var count = ViewState["txtBoxCount"]; 
      return (count == null) ? 0 : (int) count; 
     } 
     set { ViewState["txtBoxCount"] = value; } 
    } 

    private void AddTextBox(int index) 
    { 
     var panel = new Panel(); 
     panel.Controls.Add(new TextBox {ID = string.Concat("txtDynamic", index)}); 
     var btn = new Button { Text="Remove" }; 
     btn.Click += btnRemove_Click; 
     panel.Controls.Add(btn); 
     phControls.Controls.Add(panel); 
    } 

    private void btnRemove_Click(object sender, EventArgs e) 
    { 
     var btnRemove = sender as Button; 
     if (btnRemove == null) return; 
     btnRemove.Parent.Visible = false; 
    } 
} 
+0

muchas gracias amigo! ¡Esto es lo que estaba buscando! – Shaokan

+0

Me alegro de poder ayudar. – rsbarro

+0

¿Qué tal si quiero eliminar el cuadro de texto dinámico? Inserto un botón y le asigno un evento cada vez que se crea un cuadro de texto.En realidad, en el primer clic, el cuadro de texto se borra con éxito, pero luego pueden ocurrir algunos errores (no excepciones, pero por ejemplo, el valor del libro de texto no se guarda al hacer clic). ¿Hay alguna manera fácil de eliminar el cuadro de texto especificado? – Shaokan

1

leí un artículo de Scott Mitchell que explica que ViewState sólo persiste estado de control cambiada a través de post-atrás, y no los propios controles reales. No tenía su escenario exacto, pero un proyecto en el que estaba trabajando requería controles de usuario agregados dinámicamente y tuve que agregarlos en cada devolución. En ese caso, aún es útil crearlos en Init para que puedan conservar su estado. Aquí está el enlace: Understanding ASP.NET View State. Ver la sección "Ver controles de estado y dinámicamente agregados".

Es posible que deba realizar un seguimiento de todos los controles que está agregando (en el estado de la sesión, por ejemplo) y volver a crearlos en la parte posterior de la publicación. Acabo de hacer una pequeña prueba donde guardo un List<string> de todos los identificadores de Textbox en Session. En la devolución, recreé todos los cuadros de texto.

+0

muchas gracias! Supongo que tengo mucho que leer mientras estoy de vacaciones :) – Shaokan

Cuestiones relacionadas