Domanda

Riepilogo

Ciao a tutti,
OK, proseguiamo nelle mie avventure con i controlli personalizzati...

In sintesi, ecco che ho appreso dell'esistenza di tre "classi" principali di controlli personalizzati.Per favore, sentitevi liberi di correggermi se qualcosa di tutto ciò è sbagliato!

  1. Controlli utente - Da cui ereditare Controllo utente e sono contenuti all'interno di un ASCX file.Ciò che possono fare è piuttosto limitato, ma rappresenta un modo rapido e leggero per ottenere alcuni punti in comune dell'interfaccia utente con il supporto del designer.
  2. Controlli compositi personalizzati -Questi sono controlli che ereditano da Controllo Web dove aggiungi controlli preesistenti al controllo all'interno di CreateChildControls metodo.Ciò fornisce grande flessibilità, ma mancanza di supporto da parte del progettista senza codifica aggiuntiva.Sono tuttavia altamente portabili poiché possono essere compilati in una DLL.
  3. Controlli con rendering personalizzato - Simili ai controlli compositi personalizzati, questi vengono aggiunti a un progetto di libreria di controlli Web.Il rendering del controllo è completamente controllato dal programmatore sovrascrivendo il file Render metodo.

I miei pensieri..

OK, quindi mentre giocavo con i compositi personalizzati, ho trovato quanto segue:

  • Hai poco/nessun controllo sull'output HTML rendendo difficile il "debug".
  • IL CreateChildControls (e i metodi successivi) possono essere molto impegnati Controls.Add(miocontrollo) ovunque.
  • Ho trovato le tabelle di rendering (sia per il layout che per il contenuto) notevolmente imbarazzanti.

Le domande)..

Quindi, lo ammetto, sono nuovo in questo campo, quindi potrei essere molto fuori strada con alcuni dei punti sopra indicati...

  • Usi i compositi?
  • Hai qualche trucco accurato per controllare l'output HTML?
  • Dici semplicemente "al diavolo tutto" e vai avanti e crei un controllo con rendering personalizzato?

È qualcosa che desidero avere ben fermo nella mia mente poiché so quanto Bene lo sviluppo del controllo può ridurre i tempi di sviluppo complessivi.

Aspetto con ansia le vostre risposte ^_^

È stato utile?

Soluzione

Dico di andare avanti con il controllo reso personalizzato.Trovo che nella maggior parte dei casi il composito possa essere più semplice da realizzare e utilizzare in un UserControl, ma qualsiasi cosa oltre a ciò e dovresti avere un grado di controllo più preciso (gioco di parole non intenzionale) per meritare la tua strategia di rendering.

Forse ci sono controlli abbastanza semplici da meritare un composito (ad esempio, una casella di testo combinata con un datepicker basato su javascript/dhtml, ad esempio) ma oltre a questo esempio, sembra che i controlli renderizzati personalizzati siano la strada da percorrere.

Altri suggerimenti

Ecco un altro metodo di estensione che utilizzo per il rendering personalizzato:

 public static void WriteControls
        (this HtmlTextWriter o, string format, params object[] args)
 { 
    const string delimiter = "<2E01A260-BD39-47d0-8C5E-0DF814FDF9DC>";
    var controls  = new Dictionary<string,Control>();

    for(int i =0; i < args.Length; ++i)
    { 
       var c = args[i] as Control; 
       if (c==null) continue;
       var guid = Guid.NewGuid().ToString();
       controls[guid] = c;
       args[i] = delimiter+guid+delimiter;
    }

    var _strings = string.Format(format, args)
                         .Split(new string[]{delimiter},
                                StringSplitOptions.None);
    foreach(var s in _strings)
    { 
       if (controls.ContainsKey(s)) 
           controls[s].RenderControl(o);
       else 
           o.Write(s);
    }
}

Quindi, per eseguire il rendering di un composito personalizzato nel metodo RenderContents() scrivo questo:

protected override void RenderContents(HtmlTextWriter o)
{ 
    o.WriteControls
         (@"<table>
               <tr>
                    <td>{0}</td>
                    <td>{1}</td>
               </tr>
             </table>"
            ,Text
            ,control1);
 }

Roby, hai ragione.L’approccio che ho menzionato è una specie di ibrido.Il vantaggio di avere file ascx in giro è che su ogni progetto che ho visto, i designer si sentirebbero più a loro agio nel modificare il markup effettivo e con ascx tu e un designer potete lavorare separatamente.Se non prevedi di apportare modifiche effettive a CSS/markup/design sui controlli stessi in un secondo momento, puoi utilizzare un controllo renderizzato personalizzato.Come ho detto, il mio approccio è rilevante solo per scenari più complicati (e questi sono probabilmente quelli in cui hai bisogno di un designer :))

Utilizzo spesso i controlli compositi.Invece di sovrascrivere Render o RenderContents, basta assegnare a ciascun Control una CssClass e utilizzare i fogli di stile.Per più Controls.Add, utilizzo un metodo di estensione:

//Controls.Add(c1, c2, c3)
static void Add(this ControlCollection coll, params Control[] controls)
 { foreach(Control control in controls) coll.Add(control);
 }

Per un rendering rapido e sporco, utilizzo qualcosa del genere:

writer.Render(@"<table>
                   <tr><td>{0}</td></tr>
                   <tr>
                       <td>", Text);
control1.RenderControl(writer);
writer.Render("</td></tr></table>");

Per inizializzare le proprietà del controllo, utilizzo la sintassi dell'inizializzatore di proprietà:

childControl = new Control {  ID="Foo"
                            , CssClass="class1"
                            , CausesValidation=true;
                           };

L'uso di controlli compositi personalizzati è utile in una situazione in cui si dispone di un'applicazione Web di grandi dimensioni e si desidera riutilizzare parti di grandi dimensioni in molti posti.Quindi aggiungeresti solo i controlli secondari di quelli che stai sviluppando invece di ripeterti.Su un grande progetto a cui ho lavorato di recente, quello che abbiamo fatto è il seguente:

  • Ogni controllo composito ha un contenitore.Utilizzato come avvolto per tutto ciò che è all'interno del controllo.
  • Ogni controllo composito ha un modello.Un file ascx (senza la direttiva <%Control%>) che contiene solo il markup per il modello.
  • Il contenitore (essendo esso stesso un controllo) viene inizializzato dal modello.
  • Il contenitore espone le proprietà per tutti gli altri controlli nel modello.
  • Utilizzi solo this.Controls.Add([the_container]) nel tuo controllo composito.

In effetti è necessaria una classe base che si occupi di inizializzare un contenitore con il modello specificato e lanci anche eccezioni quando un controllo non viene trovato nel modello.Naturalmente questo potrebbe essere eccessivo in una piccola applicazione.Se non hai riutilizzato codice e markup e desideri solo scrivere controlli semplici, è meglio utilizzare i controlli utente.

Potresti essere in grado di utilizzare questa tecnica per semplificare la fase di progettazione:

http://aspadvice.com/blogs/ssmith/archive/2007/10/19/Render-User-Control-as-String-Template.aspx

Fondamentalmente crei un'istanza di un controllo utente in fase di esecuzione utilizzando il metodo LoadControl, quindi gli passi uno stato di qualche tipo, quindi lo colleghi all'albero di controllo.Quindi il tuo controllo composito funzionerebbe effettivamente come più di un controller e il file .ascx sarebbe come una vista.

Ciò ti eviterebbe la fatica di dover creare un'istanza dell'intero albero di controllo e definire lo stile del controllo in C#!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top