2011-03-25 13 views
5

Tengo una página que he creado que genera dinámicamente controles de usuario. Por ejemplo, el control de usuario tiene dos campos que se pueden editar: SomeId y SomeData. Quiero poder establecer estos valores según un UserControlObject. Cuando leo el control después, quiero poder devolver un UserControlObject desde el control y configurar los valores de la base de datos para eso. Tengo problemas para mantener los valores actualizados.Los controles de usuario dinámicos obtienen y mantienen valores después de las devoluciones de datos

//Page 
public class SomePage 
{ 
    private List<MyUserControl> _MyUserControls; 

    private void InitControls() 
    { 
     var controlsToBuild = SomeDatabaseCallToGetControlObjects(); 

      foreach(MyUserControl control in controlsToBuild) 
      { 
     MyUserControl control = this.Page.LoadControl("MyControl.ascx") as MyUserControl; 

      UserControlPlaceHolder.Controls.Add(myControl); 
      _MyUserControls.Add(myControl); 
     } 
    } 

    protected void Page_Init(object sender, EventArgs e) 
    { 
     InitControls(); 
    } 

    protected void SaveButton_Click(object sender, EventArgs e) 
    { 
     if (this.IsValid) 
     { 
     List<MyUserObject>listObj = new List<MyUserObject>(); 
     foreach(MyUserControl control in _MyUserControls) 
     { 
      MyUserObject obj = control.GetObjectFromControl(); 
      listObjs.Add(obj); 
     } 
     SaveToDatabase(listObjs); 
     //Clear placeholder in case number of controls has changed based on the save 
     UserControlPlaceHolder.Clear(); 
     InitControls(); 
     GetObjectFromDatabase(); 
     } 
    } 

} 

//Object to put in control 
public class UserControlObject 
{ 
    public string DataForUser { get;set;} 
    public double MoreDataForUser { get;set;} 
    public int HiddenIdFromUser { get; set;} 
} 


//User control 
public class MyUserControl : UserControl 
{ 

    public MyUserControlObject GetObjectFromControl() 
    { 
    UserControlObject obj = new UserControlObject(); 
    obj.DataForUser = textBoxOnTheControl.Text; 
    obj.MoreDataForUser = anotherBoxOnTheControl.Text; 
    obj.HiddenIdFromUser = hiddenField.Value; 

    return obj; 
    } 

    public void SetUserControlObject(UserControlObject obj) 
    { 
    textBoxOnTheControl.Text = obj.DataForUser; 
    anotherBoxOnTheControl.Text = obj.MoreDataForUser; 
    hiddenField.Value = obj.HiddenIdFromUser; 
    } 
} 

Básicamente, quiero que cargar cada MyUserControl con los valores de una base de datos. Un usuario debería poder cambiar la mayoría (pero no todos) de esos campos. Un usuario no debería poder cambiar la ID, pero necesito actualizar el registro en la base de datos.

Tengo problemas para guardar la información y conservarla correctamente, porque estoy volviendo a crear una colección de MyUserControl. Parece funcionar bien en la devolución de datos inicial, pero después de posteriores devoluciones de datos, todavía obtengo el valor anterior para uno de los campos. ¿Cómo puedo asegurarme de que:

1) La información se establece correctamente en el/los control (es) del usuario. ¿Debo colocar una propiedad pública que haga referencia a viewstate en cada propiedad del UserControl?

2) ¿Después de hacer clic en un evento de guardar, después de la devolución de datos, la reconstrucción de los controles no me hará retener ningún valor "anterior" de la carga inicial? ¿Cómo debo manejar viewstate aquí? Quiero que los datos reflejen todo lo que el usuario ha cambiado.

+0

Estoy tratando de seguir su código, hay un par de problemas que lo hacen difícil de seguir. En 'InitControls()' tiene un bucle 'foreach', pero creo que tiene la intención de que sea un bucle simple, ¿no? es decir, 'for (int i = 0; i

+0

@Joel: Ha sido un día largo ... He hecho las correcciones :) –

Respuesta

9

Para que el estado de visualización/control funcione correctamente, debe tener la misma ID para sus controles. Como no está asignando ID de forma explícita, debe generar y habrá conflictos allí con más de un control de usuario presente. Le recomendaré que tenga algún tipo de lógica para generar el mismo conjunto de ID que el posterior. Por ejemplo,

private void InitControls() 
{ 
    var numControlsToBuild = SomeDatabaseCallToGetNumControls(); 
    int idCounter = 1; 
    foreach(var controlData in numControlsToBuild) 
    { 
    var control = this.Page.LoadControl("MyControl.ascx") as MyUserControl; 
    control.ID = "MyControl" + idCounter.ToString(); 
    idCounter++; 
    UserControlPlaceHolder.Controls.Add(myControl); 
    _MyUserControls.Add(control); 

    // probably code load control data into control 
    } 
} 
+0

+1 Este es de hecho el problema central aquí. Voy a publicar otra respuesta para entrar en más detalles. –

+0

Esto solucionó el problema. Gracias por tu contribución. –

4

Como ha señalado VinayC, el problema fundamental aquí es debido al hecho de que cuando se agrega controles dinámicamente a una página, si no se asigna identificadores de esos controles, se les dará generan IDs. Si la cantidad de controles generados dinámicamente cambia, o si el orden en el que se crearon cambia, entonces habrá una falta de coincidencia entre los controles web creados dinámicamente y la información de estado para esos objetos en el estado de vista. De forma similar, habrá una falta de coincidencia entre los ID de los controles web creados dinámicamente y los ID de los parámetros de consulta en los encabezados POST. Eso significa que los valores de algunos campos no se actualizarán a partir de los datos POST.

Ver desajustes de ID de estado hará que cosas como etiquetas y literales vuelvan a los valores iniciales. Por otro lado, las discrepancias de ID de datos POST provocarán campos de entrada para volver a los valores iniciales. Si tiene problemas con los campos de entrada que revierten a los valores iniciales, desordenar alrededor con el estado de vista no resolverá el problema. Es un concepto erróneo común que los valores de campo se mantienen en el estado de vista. Sin embargo, esto es innecesario porque los valores del campo de entrada ya están contenidos en los datos POST. Para una buena discusión de cómo funciona View State, vea Understanding how the viewstate works por Scott Mitchell.

Si siempre crea sus controles agregados dinámicamente en el mismo orden, como VinayC señala, puede generar una secuencia de ID como "ID1", "ID2", "ID3", ... como lo es creando los controles web. En su caso, dado que está almacenando sus valores de campo de Control de usuario en una base de datos, puede generar nuevos identificadores para cada control de usuario solo una vez y almacenar cada ID generada en la base de datos junto con los valores de campo asociados. De esta forma, no debe preocuparse por el orden en que crea los controles.

Cuestiones relacionadas