sì, alla fine ho fatto proprio così per recuperare i valori dei controlli dinamici ...grazie ancora!

Anche se sono alle prime armi con .net e il mio codice apparirà 'ridicolo' ai più ferrati in materia lo posto lo stesso affinchè possa aiutare chi si trova nella situazione di dover gestire un numero NON noto di controlli. Le seguenti funzioni generano la tabella di controlli dinamici come mostrato nello screenShot2 del mio wizard.


Si parte con il ciclo che genera il numero NON noto di records e gli si mette all'interno una chiamata ad una funzione che crei, in base ai parametri passati, i controlli necessari a personalizzare le informazioni e le funzioni ad essi associate:
codice:
While dataReader.Read() ' ciclo che verrà eseguito N volte a seconda dei record trovati
    ' Creo una riga di controlli precompilati con i dati presi dal database
    CrateCustomizationRow(dataReader("suffisso_del_nome_dei_controlli_da_creare"), dataReader("quantity"), dataReader("partNumber"), dataReader("description"))
End While
La funzione CreateCustomizationRow (credo che sia molto ottimizzabile):
codice:
Protected Function CrateCustomizationRow(ByVal wich As String, ByVal Qt As String, ByVal PN As String, ByVal description As String) As String
    'Crea riga di personalizzazione: 
    'CustomJobPlaceHolder è all'interno di due tag <table></table> per creare_
    'i controlli all'interno di una tabella con <div> switchabili da visibili a invisibili.
    Dim strHtml As New Literal
    strHtml.Text = "<tr id='tr" & wich & "' runat='server'><td style='width: 21px'>"
    CustomJobPlaceHolder.Controls.Add(strHtml)
    Dim chkSwitch As New CheckBox
    Dim nomeChkBox As String = "chkCustomize" & wich
    chkSwitch.ID = nomeChkBox
    chkSwitch.Attributes.Add("onClick", "switchCustomizationRow('" & wich & "');")
    CustomJobPlaceHolder.Controls.Add(chkSwitch)
    '----
    Dim strHtml2 As New Literal
    strHtml2.Text = "</td><td style='width: 24px' align='center'><div id='div" & wich & "LblQt'>" & Qt & "</div><div id='div" & wich & "TBQt' style='display = none'>"
    CustomJobPlaceHolder.Controls.Add(strHtml2)
    Dim TBQt As New TextBox
    Dim nomeTxtBox As String = "TBQt" & wich
    TBQt.ID = nomeTxtBox
    TBQt.CssClass = "userInput"
    TBQt.Width = "24"
    TBQt.Text = Qt
    CustomJobPlaceHolder.Controls.Add(TBQt)
    '----
    Dim strHtml3 As New Literal
    strHtml3.Text = "</div></td><td width='79'><div id='div" & wich & "LblPn'>" & PN & "</div><div id='div" & wich & "TBPn' style='display = none'>"
    CustomJobPlaceHolder.Controls.Add(strHtml3)
    Dim TBPn As New TextBox
    nomeTxtBox = "TBPn" & wich
    TBPn.ID = nomeTxtBox
    TBPn.CssClass = "userInput"
    TBPn.Width = "79"
    TBPn.Text = PN
    CustomJobPlaceHolder.Controls.Add(TBPn)
    '----
    Dim strHtml4 As New Literal
    strHtml4.Text = "</div></td><td width='479'><div id='div" & wich & "LblDescription'>" & description & "</div><div id='div" & wich & "TBDescription' style='display = none'>"
    CustomJobPlaceHolder.Controls.Add(strHtml4)
    Dim TBDescription As New TextBox
    nomeTxtBox = "TBDescription" & wich
    TBDescription.ID = nomeTxtBox
    TBDescription.CssClass = "userInput"
    TBDescription.Width = "479"
    TBDescription.Text = description
    CustomJobPlaceHolder.Controls.Add(TBDescription)
    '----
    Dim strHtml5 As New Literal
    strHtml5.Text = "</div></td>"
    CustomJobPlaceHolder.Controls.Add(strHtml5)
    '----
    Dim strHtml6 As New Literal
    strHtml6.Text = "</div></td><td width='18' align='center'><div id='div" & wich & "LnkSelectorInactive'>[img]images/search-blue-off.gif[/img]</div>"
    strHtml6.Text += "<div id='div" & wich & "LnkSelector' style='display = none'>[img]images/search-blue.gif[/img]</div></td></tr>"
    CustomJobPlaceHolder.Controls.Add(strHtml6)
End Function 'Crea riga di personalizzazione
La funzione javascript per gestire lo stato dei controlli dinamici:
codice:
<script type="text/javascript">
    function switchCustomizationRow(wich) {
        // Cambia lo stato di una riga da visualizzazione a editing
        if(eval("document.getElementById('WizardAck$chkCustomize" + wich + "').checked")){
	        eval("document.getElementById('tr" + wich + "').style.backgroundColor  = '#e1e1ff'");
	        eval("document.getElementById('div" + wich + "LblQt').style.display = 'none'");
	        eval("document.getElementById('div" + wich + "LblPn').style.display = 'none'");
	        eval("document.getElementById('div" + wich + "LblDescription').style.display = 'none'");
	        eval("document.getElementById('div" + wich + "LnkSelectorInactive').style.display = 'none'");
	        eval("document.getElementById('div" + wich + "TBQt').style.display = 'inline'");
	        eval("document.getElementById('div" + wich + "TBPn').style.display = 'inline'");
	        eval("document.getElementById('div" + wich + "TBDescription').style.display = 'inline'");
	        eval("document.getElementById('div" + wich + "LnkSelector').style.display = 'inline'");
        }else{
	        eval("document.getElementById('tr" + wich + "').style.backgroundColor  = '#ffffff'");
	        eval("document.getElementById('div" + wich + "LblQt').style.display = 'inline'");
	        eval("document.getElementById('div" + wich + "LblPn').style.display = 'inline'");
	        eval("document.getElementById('div" + wich + "LblDescription').style.display = 'inline'");
	        eval("document.getElementById('div" + wich + "LnkSelectorInactive').style.display = 'inline'");
	        eval("document.getElementById('div" + wich + "TBQt').style.display = 'none'");
	        eval("document.getElementById('div" + wich + "TBPn').style.display = 'none'"); 
	        eval("document.getElementById('div" + wich + "TBDescription').style.display = 'none'");
	        eval("document.getElementById('div" + wich + "LnkSelector').style.display = 'none'");
        }
    }    
</script>
Alla fine, con una copia del ciclo che ha generato i controlli, possiamo recuperare e valutare i valori di tutti i controlli generati:
codice:
While dataReader.Read() ' ciclo che verrà eseguito N volte a seconda dei record trovati
    'N.B. Al nome del controllo va aggiunto il prefisso del nome del Wizard che lo contiene_
    'in questo caso: "WizardAck$"  (non necessario se non si è in un Wizard)
    Dim CB As CheckBox = DirectCast(Page.FindControl("WizardAck$" & dataReader("suffisso_del_nome_dei_controlli_da_creare")), CheckBox)
    If Not CB.Checked Then
        'Inserisco nel database i valori NON personalizzati
    Else
        Dim TBQt As TextBox = DirectCast(Page.FindControl("WizardAck$" & dataReader("suffisso_del_nome_dei_controlli_da_creare")), TextBox)
        Dim TBPn As TextBox = DirectCast(Page.FindControl("WizardAck$" & dataReader("suffisso_del_nome_dei_controlli_da_creare")), TextBox)
        Dim TBDescription As TextBox = DirectCast(Page.FindControl("WizardAck$TBDescriptionMotorPulley"), TextBox)
        'Inserisco nel databse i valori inseriti dall'utente_
        'nelle caselle di personalizzazione di questo componente
    End If
End While


La altre funzioni JavaScript che si vedono associati agli ultimi due link della funzione CreateCustomizationRow servono ad aprire un Flyout (componente gratuito) che permette di scegliere da una gridview (in un iframe) un'eventuale componente dal database per sostituirlo a quello proposto.
Questo lo faccio perchè, a volte, l'utente può voler semplicemente sostituire una voce senza doverci scrivere nulla di particolare a mano.
La funzione "updateFromSelector" passa i valori dall'iframe del Flyout alla riga di personalizzazione che ha invocato la funzione.

Posto solo il codice javascript perchè questa parte è assolutamente superflua:
codice:
<script type="text/javascript">
    function attachFlyoutToLink(oLink,component) {
        // Attacca un Flyout all'oggetto (oLink) passato come parametro
        try {
            <%=Flyout1.getClientID()%>.setPosition("ABSOLUTE",""); 
            <%=Flyout1.getClientID()%>.setRelativePosition(-690,15);		            
            <%=Flyout1.getClientID()%>.setOpenTime(200);
            <%=Flyout1.getClientID()%>.AttachTo(oLink.id);
            var sNewHtml = getRecordInfo(component);
            document.getElementById("divFlyoutContent").innerHTML = sNewHtml;
            <%=Flyout1.getClientID()%>.Open();
        } catch(ex){}		    	
    }	
    
    function closeFlyout() {
        <%=Flyout1.getClientID()%>.Close();
    }
    
    function getRecordInfo(component) {
        // Apro l'iframe passandogli in querystring il nome del componente_
        // in modo che possa offrirmi una lista di alternative
        var sNewHtml = "<table cellspacing='0' cellpadding='0' width='100%'>";
        sNewHtml += "<tr><td class='titoli' bgcolor='#ececec'>" + component + "</td><td class='testomedio' align='right' bgcolor='#ececec'>X</td></tr>";
        sNewHtml += "<tr><td class='testomedio' colspan='2'>";
        sNewHtml += "<IFRAME scrolling='no' frameborder='0' style='height:196; width:690;' src='PNselector.aspx?searchFor=" + component + "'></IFRAME>";
        sNewHtml += "</td></tr>";
        sNewHtml += "</table>";
        return sNewHtml;
    }
    	
    function inactiveLink() {
        // Notifico che non si può scegliere un componente sostitutivo se non si ha cliccato_
        // il checkBox della personalizzazione
        alert('Attivare la personalizzazione della riga per accedere a questa funzione.');
    }
    
    function updateFromSelector(PN,description,from) {
        // Passo i valori dal Flyout alla riga che l'ha invocatoù
        // N.B. Viene chiamata dall'iframe tramite: parent.updatreFromSelector(..parametri..)
        <%=Flyout1.getClientID()%>.Close();
        eval("document.getElementById('WizardAck$TBPn" + from + "').value = '" + PN + "'");
        eval("document.getElementById('WizardAck$TBDescription" + from + "').value = '" + description + "'");
    }		
</script>
Adesso sarei solo curioso di sapere se è giusto che debba creare così tanti Literal per mettere i controlli in una tabella o se sbaglio clamorosamente metodo?

Comunque sia, grazie ancora ai consigli di djciko ...ora va tutto come volevo io