Criança Inicialização de Controle em Composite personalizado no ASP.NET
-
02-07-2019 - |
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:)
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:
- eu tinha anulado a propriedade acessor
Controls
para o composto para retornar coleção Controls destePanel
desde que eu não quero ter que irctl.Controls[0].Controls[0]
para chegar ao controle real eu quero. Eu removi isso, mas eu preciso resolver isso. - Eu não tinha adicionado o
Panel
à coleçãoControls
, 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
?