Pergunta

A parte da série de controles estou trabalhando, obviamente, envolve me agregando alguns deles juntos para compósitos. Estou rapidamente começando a aprender que isso leva consideração (isto é tudo novo para mim!):)

Basicamente, eu tenho um controle StyledWindow, que é essencialmente um Panel glorificado com capacidade de fazer outros bits (como fronteiras add etc).

Aqui está o código que instancia os controles filho dentro dele. Até este ponto, parece ter sido funcionando corretamente com controles estáticos mundanas:

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

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

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

Os problemas vieram hoje quando tentei nidificação um controle mais complexo dentro dele. Este controle utiliza uma referência para a página uma vez que injeta JavaScript para torná-lo um pouco mais ágil e responsiva (a RegisterClientScriptBlock é a única razão que eu preciso na página ref).

Agora, isso estava causando erros "objeto nulo", mas eu localizada esse baixo para o método de renderização, que foi, naturalmente, a tentar chamar o método contra o [nulo] objeto Page.

O que está me confundindo é que o controle funciona bem como um autônomo, mas quando colocado no StyledWindow tudo vai! Horrivelmente errado

Assim, parece que eu estou faltando alguma coisa em qualquer meu StyledWindow ou ChildControl. Alguma idéia?

Atualização

Como Brad Wilson salientou muito bem , você não vê os controles a ser adicionados à coleção Controls. Isto é o que o _panel é para, este estava lá para lidar com isso para mim, basicamente, em seguida, substituir Controls (eu tenho isso de um lugar guia):

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

Espero que ajuda a esclarecer as coisas. Desculpas.

Atualização Após Resposta do Longhorn213

Certo, eu tenho feito algumas jogar com o controle, colocando um dentro do composto, e um fora. Então eu tenho o status da página no evento grande evento no controle do ciclo de vida e tornou-o para a página.

O autônomo está funcionando bem e que a página é inited como esperado. No entanto, a única aninhado no Composite é diferente. É do evento OnLoad não está sendo disparado em tudo! Então, eu estou supondo que Brad está provavelmente certo em que não estou a configuração da hierarquia de controle corretamente, alguém pode oferecer alguns conselhos sobre o que eu estou ausente? É o método do Painel não é suficiente? (Bem, é óbvio que não é é ?!): D

Obrigado por sua ajuda caras, apreciada:)

Foi útil?

Solução 3

resolvido!

Certo, eu estava determinado a conseguir este rachado hoje! Aqui foram meus pensamentos:

  • Eu pensei que o uso de Panel foi um pouco de um truque, então eu deveria removê-lo e descobrir como ele é realmente feito.
  • Eu não queria ter que fazer algo como MyCtl.Controls[0].Controls para acessar os controles adicionados ao composto.
  • Eu queria que a maldita coisa para o trabalho!

Então, eu fui pesquisando e bateu MSDN , este artcle era realmente útil (ou seja, como quase copiar 'n' colar, e explicou bem - algo MSDN é tradicionalmente ruim). Bom!

Então, eu arrancado o uso de Panel e praticamente acompanhou o artcle e levou-o como um evangelho, fazendo anotações como eu fui.

Aqui está o que eu tenho agora:

  • Eu aprendi que eu estava usando o termo errado. Eu deveria ter sido chamando-a de controle modelo . Enquanto que os controlos modeladas são tecnicamente compósitos, há uma diferença distinta. controles Templated pode definir a interface para os itens que são adicionados a eles.
  • controles Templated são muito poderosos e realmente muito rápido e fácil de configurar uma vez que a sua cabeça em volta deles!
  • Eu vou jogar um pouco mais com o apoio de designer para garantir que eu compreendo perfeitamente tudo isso, então, fazer um post no blog up:)
  • Um controle "modelo" é usado para especificar a interface para os dados templated.

Por exemplo, aqui está a marcação ASPX para um controle modelo:

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

Heres o código que eu tenho agora

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

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

Então, para facilitar o acesso aos controles do Object [substituto]:

(é por isso que precisávamos para limpar / adicionar aos base.Controls)

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

E isso é muito bonito isso, fácil quando você sabe como! :)

Seguinte: Design Região Apoio Tempo

Outras dicas

Eu não vê-lo adicionando seus controles para a qualquer lugar coleção Controls, o que explicaria por que eles não podem acessar a página (uma vez que nunca foi oficialmente colocado na página).

Eu sempre colocar as chamadas JavaScript na função OnLoad. Tal como abaixo.

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 você ainda quer fazer o render, então você pode apenas escrever o script na resposta. Que é o que o RegisterScriptBlock faz, ele apenas coloca a linha de script na página.

Certo, eu me jogar e eu percebi que havia algo de errado com a minha instanciação de controle, uma vez Longhorn estava certo, eu deveria ser capaz de criar referências de script em OnLoad (e eu não poderia), e Brad estava certo em que Eu preciso para garantir a minha hierarquia Controls foi mantida pela adição à coleção Controls do compósito.

Então, eu tinha duas coisas aqui:

  1. eu tinha anulado a propriedade acessor Controls para o composto para retornar coleção Controls deste Panel desde que eu não quero ter que ir ctl.Controls[0].Controls[0] para chegar ao controle real eu quero. Eu removi isso, mas eu preciso resolver isso.
  2. Eu não tinha adicionado o Panel à coleção Controls, Eu já fiz isso.

Assim, ele trabalha agora, no entanto, como faço para obter a propriedade Controls para o composto para devolver os itens no Panel, ao invés do próprio Panel?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top