Question

Une partie de la série de contrôles sur laquelle je travaille implique évidemment que je mette certains d'entre eux dans des composites. Je commence rapidement à apprendre que cela prend en compte (c'est tout nouveau pour moi!):)

J'ai essentiellement un contrôle StyledWindow , qui est essentiellement un panneau glorifié avec la possibilité de faire d'autres bits (comme ajouter des bordures, etc.).

Voici le code qui instancie les contrôles enfants qu’il contient. Jusque là, il semble avoir fonctionné correctement avec les contrôles statiques ordinaires:

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

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

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

Les problèmes sont survenus aujourd’hui lorsque j’ai essayé d’imbrouiller un contrôle plus complexe à l’intérieur. Ce contrôle utilise une référence à la page car il injecte du JavaScript dans celui-ci pour le rendre un peu plus réactif et réactif (le RegisterClientScriptBlock est la seule raison pour laquelle j'ai besoin de la référence de la page).

À présent, cela entraînait " object null " erreurs, mais j’ai localisé cela dans la méthode de rendu, qui essayait bien sûr d’appeler la méthode avec l’objet [null] Page .

Ce qui me dérange, c’est que le contrôle fonctionne correctement en autonome, mais qu’il est placé dans StyledWindow , il se passe terriblement mal!

Il semble donc qu'il me manque quelque chose dans mon StyledWindow ou dans le ChildControl . Des idées?

Mettre à jour

Comme Brad Wilson a fort justement souligné , les contrôles ne sont pas ajoutés à la collection Controls . C’est à cela que sert le _panel . C’est là que j’ai pu gérer cela pour moi; fondamentalement, nous substituons ensuite Contrôles (je l’ai eu quelque part d’un guide):

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

J'espère que cela aide à clarifier les choses. Toutes mes excuses.

Mise à jour à la suite de Réponse de Longhorn213

D'accord, j'ai joué un peu avec le contrôle, en plaçant un dans le composite et un autre à l'extérieur. J'ai ensuite obtenu le statut de page lors d'un événement majeur dans le cycle de vie du contrôle et l'a rendu à la page.

La version autonome fonctionne correctement et la page est entrée comme prévu. Cependant, celui imbriqué dans le composite est différent. C'est l'événement OnLoad n'est pas déclenché du tout! Je suppose donc que Brad a probablement raison en ce que je ne configure pas correctement la hiérarchie de contrôle. Quelqu'un peut-il donner des conseils sur ce qui me manque? La méthode du panel n'est-elle pas suffisante? (eh bien, ce n'est évidemment pas le cas?!): D

Merci pour votre aide les gars, apprécié:)

Était-ce utile?

La solution 3

résolu!

D'accord, j'étais déterminé à obtenir cette fissure aujourd'hui! Voici mes pensées:

  • Je pensais que l'utilisation de Panel était un peu un piratage. Je devrais donc le supprimer et découvrir comment cela se passe réellement.
  • Je ne voulais pas faire quelque chose comme MyCtl.Controls [0] .Controls pour accéder aux contrôles ajoutés au composite.
  • Je voulais que cette fichue chose fonctionne!

J'ai donc lancé une recherche et frappé MSDN , cet article était VRAIMENT utile (c'est-à-dire, presque comme copier / coller, et a bien expliqué - quelque chose que MSDN est traditionnellement mauvais à). Sympa!

J'ai donc arrêté d'utiliser Panneau et je suivais à la lettre l'artcle et je le prenais comme un évangile, en prenant des notes au fur et à mesure que je partais.

Voici ce que j'ai maintenant:

  • J'ai appris que j'utilisais le mauvais terme. J'aurais dû l'appeler un contrôle basé sur un modèle . Bien que les contrôles basés sur des modèles soient techniquement composites, il existe une différence nette. Les contrôles basés sur un modèle peuvent définir l'interface des éléments qui leur sont ajoutés.
  • Les commandes basées sur un modèle sont très puissantes et, en fait, faciles et rapides à configurer une fois que vous maîtrisez leur esprit!
  • Je vais en jouer un peu plus avec le support des concepteurs pour m'assurer de bien comprendre le tout, puis créer un article de blog:)
  • Un " modèle " Le contrôle est utilisé pour spécifier l'interface pour les données basées sur un modèle.

Par exemple, voici le balisage ASPX d'un contrôle basé sur un modèle:

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

Voici le code que j'ai maintenant

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

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

Ensuite, pour faciliter l'accès aux commandes de l'objet [Surrogate]:

(c'est pourquoi nous avions besoin d'effacer / d'ajouter à la base.Controls)

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

Et c'est à peu près tout, facile quand on sait comment faire! :)

Suivant: Prise en charge des régions au moment du design!

Autres conseils

Je ne vois pas que vous ajoutiez vos contrôles à la collection de contrôles, ce qui expliquerait pourquoi ils ne peuvent pas accéder à la page (car ils n'ont jamais été officiellement placés sur la page).

J'ai toujours mis les appels JavaScript sur la fonction OnLoad. Comme ci-dessous.

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

Si vous souhaitez toujours effectuer le rendu, vous pouvez simplement écrire le script dans la réponse. C'est ce que fait RegisterScriptBlock. Il insère simplement le script dans la page.

Bien, j'ai commencé à jouer et je me suis dit qu'il y avait quelque chose qui n'allait pas avec mon instanciation de contrôle. Comme Longhorn avait raison, je devrais pouvoir créer des références de script à OnLoad (et je ne pouvais pas le faire). et Brad avait raison de dire que je devais vérifier que ma hiérarchie Controls était maintenue en ajoutant des éléments à la collection Controls du composite.

Donc, j'avais deux choses ici:

  1. J'avais écrasé l'accesseur de propriété Controls du composite pour renvoyer la collection Controls de ce Panel car je ne voulais pas avoir à aller ctl.Controls [ 0] .Controls [0] pour obtenir le contrôle réel que je veux. J'ai supprimé ceci, mais je dois le faire.
  2. Je n'avais pas ajouté le Panneau à la collection Controls , je viens de le faire.

Donc, cela fonctionne maintenant, cependant, comment obtenir la propriété Controls du composite pour renvoyer les éléments du Panel , plutôt que le < code> Panneau lui-même?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top