2011-03-25 3 views
5

Ho una pagina che ho creato che genera dinamicamente i controlli utente. Ad esempio, il controllo utente ha due campi che possono essere modificati: SomeId e SomeData. Voglio essere in grado di impostare questi valori in base a un UserControlObject. Quando leggerò il controllo in seguito, voglio essere in grado di restituire un controllo UserControlObject e impostare i valori del database su quello. Sto avendo qualche problema a far sì che i valori rimangano aggiornati.I controlli utente dinamici acquisiscono e mantengono i valori dopo i postback

//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; 
    } 
} 

Fondamentalmente, voglio caricare ogni MyUserControl con i valori da un database. Un utente dovrebbe essere in grado di modificare la maggior parte (ma non tutti) di quei campi. Un utente non dovrebbe essere in grado di modificare l'ID, ma ho bisogno che aggiorni il record nel database.

Ho difficoltà ad ottenere le informazioni da salvare e persistere correttamente, perché sto ricreando una raccolta di MyUserControl. Sembra funzionare bene nel postback inital, ma dopo i successivi postback, ottengo ancora il vecchio valore per uno dei campi. Come posso assicurarmi che:

1) Le informazioni sono impostate correttamente sui controlli utente. Devo inserire una proprietà pubblica che faccia riferimento a viewstate su ogni proprietà di UserControl?

2) Dopo aver fatto clic su un evento di salvataggio, dopo il postback, la ricostruzione dei controlli non mi imporrà di mantenere alcun valore "vecchio" dal carico iniziale? Come dovrei gestire il viewstate qui? Voglio che i dati riflettano ciò che l'utente ha cambiato.

+0

Sto provando a seguire il tuo codice, ci sono un paio di problemi che rendono difficile seguirlo. In 'InitControls()' hai un ciclo 'foreach', ma penso che tu intenda che sia un loop semplice, vero? per '(int i = 0; i

+0

@Joel: è stata una lunga giornata ... ho apportato le correzioni :) –

risposta

9

Perché lo stato di visualizzazione/stato di controllo funzioni correttamente, è necessario disporre dello stesso ID per i controlli. Dato che non stai assegnando l'ID esplicitamente, deve essere generato e ci sarebbero dei conflitti lì con più di un controllo utente presente. Ti consiglierò di avere un qualche tipo di logica per generare lo stesso set di ID sul post-back. Ad esempio,

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 Questo è davvero il problema principale qui. Ho intenzione di pubblicare un'altra risposta per entrare un po 'più in dettaglio. –

+0

Questo ha risolto il problema. Grazie per il tuo contributo. –

4

Come sottolineato dal VinayC, il problema fondamentale qui è dovuto al fatto che quando si aggiungere dinamicamente controlli a una pagina, se non si assegna gli ID per i controlli, che saranno dati generati ID. Se il numero di controlli generati dinamicamente cambia o se l'ordine in cui vengono creati cambia, si verificherà una mancata corrispondenza tra i controlli Web creati dinamicamente e le informazioni di stato per tali oggetti nello stato di visualizzazione. Allo stesso modo, si verificherà una mancata corrispondenza tra gli ID dei controlli Web creati dinamicamente e gli ID dei parametri di query nelle intestazioni POST. Ciò significa che i valori di alcuni campi non verranno aggiornati dai dati POST.

Le mancate corrispondenze di ID stato causano operazioni come etichette e valori letterali per ripristinare i valori iniziali. D'altra parte, i disallineamenti ID dei dati POST causeranno i campi di input per ripristinare i valori iniziali. Se si riscontrano problemi con i campi di input che tornano ai valori iniziali, lo spostamento con lo stato della vista non risolverà il problema. È un malinteso comune che i valori dei campi siano mantenuti nello stato di visualizzazione. Tuttavia, questo non è necessario perché i valori dei campi di input sono già contenuti nei dati POST. Per una buona discussione su come funziona View State, vedere Understanding how the viewstate works di Scott Mitchell.

Se crei sempre i controlli aggiunti dinamicamente nello stesso ordine, come indica VinayC, puoi generare una sequenza di ID come "ID1", "ID2", "ID3", ... come sei creando i controlli web. Nel tuo caso, dal momento che stai memorizzando i valori dei tuoi campi User Control in un database, potresti voler generare nuovi ID per ogni controllo utente solo una volta e memorizzare ogni ID generato nel database insieme ai valori dei campi associati. In questo modo, non devi preoccuparti dell'ordine in cui crei i controlli.