Domanda

Parte della serie di controlli a cui sto lavorando ovviamente mi coinvolge nel raggruppare alcuni di essi nei compositi. Sto rapidamente iniziando a sapere che questo prende in considerazione (è tutto nuovo per me!) :)

Fondamentalmente ho un controllo StyledWindow , che è essenzialmente un Pannello glorificato con la possibilità di fare altri bit (come aggiungere bordi ecc.).

Ecco il codice che crea un'istanza dei controlli figlio al suo interno. Fino a questo punto sembra aver funzionato correttamente con banali controlli statici:

    protected override void CreateChildControls()
    {
        _panel = new Panel();

        if (_editable != null)
            _editable.InstantiateIn(_panel);

        _regions = new List<IAttributeAccessor>();
        _regions.Add(_panel);
    }

I problemi sono arrivati ??oggi quando ho provato a annidare un controllo più complesso al suo interno. Questo controllo utilizza un riferimento alla pagina poiché inserisce JavaScript per renderlo un po 'più scattante e reattivo (il RegisterClientScriptBlock è l'unica ragione per cui ho bisogno del riferimento della pagina).

Ora, ciò stava causando " oggetto null " errori, ma l'ho localizzato nel metodo render, che ovviamente stava cercando di chiamare il metodo contro l'oggetto [null] Page .

Ciò che mi confonde è che il controllo funziona bene come standalone, ma quando inserito in StyledWindow tutto va terribilmente storto!

Quindi, sembra che mi manchi qualcosa nel mio StyledWindow o ChildControl . Qualche idea?

Aggiornamento

Come Brad Wilson ha giustamente sottolineato , non vedi i controlli aggiunti alla raccolta Controls . Questo è lo scopo del _panel , questo era lì per gestirlo per me, fondamentalmente quindi sovrascrivere Controls (l'ho preso da una guida da qualche parte):

    Panel _panel;    // Sub-Control to store the "Content".
    public override ControlCollection Controls
    {
        get
        {
            EnsureChildControls();
            return _panel.Controls;
        }
    }

Spero che aiuti a chiarire le cose. Scuse.

Aggiornamento dopo Risposta di Longhorn213

Bene, ho giocato un po 'con il controllo, inserendone uno all'interno del composito e uno all'esterno. Ho quindi ottenuto lo stato di Page all'evento principale dell'evento nel ciclo di vita del controllo e l'ho visualizzato nella pagina.

Il sistema autonomo funziona correttamente e la pagina viene avviata come previsto. Tuttavia, quello nidificato nel composito è diverso. È l'evento OnLoad che non viene sparato affatto! Quindi suppongo che Brad abbia probabilmente ragione nel non impostare correttamente la gerarchia dei controlli, qualcuno può offrire qualche consiglio su cosa mi sto perdendo? Il metodo Panel non è abbastanza? (beh, ovviamente non è vero ?!): D

Grazie per il vostro aiuto ragazzi, apprezzato :)

È stato utile?

Soluzione 3

risolto!

Bene, ero determinato a risolverlo oggi! Ecco i miei pensieri:

  • Ho pensato che l'uso di Panel fosse un po 'un trucco, quindi dovrei rimuoverlo e scoprire come è realmente fatto.
  • Non volevo fare qualcosa come MyCtl.Controls [0] .Controls per accedere ai controlli aggiunti al composito.
  • Volevo che la dannata cosa funzionasse!

Quindi, ho cercato e colpito MSDN , questo articolo è stato DAVVERO utile (vale a dire quasi copia e incolla, e spiegato bene - qualcosa che MSDN è tradizionalmente cattivo). Nizza!

Quindi, ho strappato l'uso di Panel e ho praticamente seguito l'artcle e l'ho preso come vangelo, prendendo appunti mentre andavo.

Ecco quello che ho adesso:

  • Ho imparato che stavo usando il termine sbagliato. Avrei dovuto chiamarlo Controllo basato su modelli . Mentre i controlli basati su modelli sono tecnicamente composti, esiste una differenza netta. I controlli basati su modelli possono definire l'interfaccia per gli elementi che vengono aggiunti ad essi.
  • I controlli basati su modelli sono molto potenti e in realtà sono piuttosto veloci e facili da configurare una volta che hai la testa intorno a loro!
  • Giocherò un po 'di più con il supporto del designer per assicurarmi di averlo compreso appieno, quindi ottenere un post sul blog :)
  • A " Template " controllo viene utilizzato per specificare l'interfaccia per i dati basati su modelli.

Ad esempio, ecco il markup ASPX per un controllo basato su modelli:

<cc1:TemplatedControl ID="MyCtl" runat="server">
    <Template>
        <!-- Templated Content Goes Here -->
    </Template>
</cc1:TemplatedControl>   

Ecco il codice che ho ora

public class DummyWebControl : WebControl
{
    // Acts as the surrogate for the templated controls.
    // This is essentially the "interface" for the templated data.
}

In TemplateControl.cs ...

    ITemplate _template;
    // Surrogate to hold the controls instantiated from 
    // within the template.
    DummyWebControl _owner;

    protected override void CreateChildControls()
    {
        // Note we are calling base.Controls here
        // (you will see why in a min).
        base.Controls.Clear();
        _owner = new DummyWebControl();

        // Load the Template Content
        ITemplate template = _template;
        if (template == null)
            template = new StyledWindowDefaultTemplate();
        template.InstantiateIn(_owner);

        base.Controls.Add(_owner);
        ChildControlsCreated = true;
    }

Quindi, per fornire un facile accesso ai controlli dell'oggetto [Surrogate]:

(ecco perché dovevamo cancellare / aggiungere alla base.Controls)

    public override ControlCollection Controls
    {
        get
        {
            EnsureChildControls();
            return _owner.Controls;
        }
    }

E questo è abbastanza, facile quando sai come! :)

Avanti: Supporto per la regione del tempo di progettazione!

Altri suggerimenti

Non ti vedo aggiungere i tuoi controlli alla raccolta Controlli da nessuna parte, il che spiegherebbe perché non possono accedere alla Pagina (dal momento che non sono mai stati ufficialmente inseriti nella pagina).

Ho sempre inserito le chiamate JavaScript nella funzione OnLoad. Come sotto.

protected override void OnLoad(EventArgs e)
{

    // Do something to get the script
    string script = GetScript();

    this.Page.ClientScript.RegisterClientScriptBlock(this.Page.GetType(), "SomeJavaScriptName", script);

    // Could also use this function to determine if the script has been register. i.e. more than 1 of the controls exists
    this.Page.ClientScript.IsClientScriptBlockRegistered("SomeJavaScriptName");

    base.OnLoad(e);
}

Se vuoi ancora eseguire il rendering, puoi semplicemente scrivere lo script nella risposta. Il che è ciò che fa RegisterScriptBlock, inserisce semplicemente lo script nella pagina.

Bene, ho iniziato a suonare e ho pensato che ci fosse qualcosa di sbagliato nella mia istanza di controllo, dato che Longhorn aveva ragione, dovrei essere in grado di creare riferimenti di script su OnLoad (e non potevo) e Brad aveva ragione nel ritenere che la mia gerarchia Controls fosse mantenuta aggiungendo alla raccolta Controls del composito.

Quindi, avevo due cose qui:

  1. Avevo scavalcato l'accessorio proprietà Controls per il composito per restituire la raccolta Controls di questo Pannello poiché non voglio andare ctl.Controls [ 0] .Controls [0] per ottenere il controllo effettivo che desidero. L'ho rimosso, ma devo ordinarlo.
  2. Non avevo aggiunto il pannello alla raccolta Controls , ora l'ho fatto.

Quindi, ora funziona, tuttavia, come posso ottenere la proprietà Controls per il composito per restituire gli elementi nel Pannello , piuttosto che < codice> Pannello stesso?

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