Usuário com melhor resposta
Registrar controle apenas 1 vez por página

Pergunta
-
Tenho uma classe de controle que deve fazer uma ação no ato do método "Render(HtmlTextWriter)", mas apenas QUANDO O PRIMERIO CONTROLE DO TIPO FOR CHAMADO. Os seguintes que estejam na mesma página (ou mesmo sub-controles da página, como em repeaters, user controls etc) NÃO DEVEM EXECUTAR A AÇÃO.
É algo assim:
public class MyControl : TextBox { protected void My1TimeAction(HtmlTextWriter writer) { //Essa é a ação que será executada ... //Ela está escrita já e funciona } protected bool IsFirstToRender() { //Aqui é que eu preciso que, se qualquer outro //Controle do tipo "MyControl" (ou derivado) nesta //Page já executou, então deve retornar "true" return false; } protected override void Render(HtmlTextWriter writer) { if (this.IsFirstToRender()) { this.My1TimeAction(writer); } base.Render(writer); } }
É possível? Um exemplo para mostrar o que deve acontecer:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="CWEB.Web.UI.DefaultPage" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="main_head" runat="server"> <meta http-equiv="content-type" content="text/html;charset=utf-8" /> <title>Central Web</title> </head> <body id="login_body"> <form id="main_login" class="main_login" runat="server"> <uc:MyControl runat="server" ID="cnt1" /> <uc:MyControl runat="server" ID="cnt2" /> <uc:MyControl runat="server" ID="cnt3" /> <uc:MyControl runat="server" ID="cnt4" /> </form> </body> </html>
Neste caso, quando "cnt1" for chamado (no método Render) ele deve executar "My1TimeAction", mas "cnt2", "cnt3" e "cnt4" NÃO PODEM EXECUTAR, porque "cnt1" já terá feito. Note, o que tem em comum é que todos estão na mesma PÁGINA - mesmo que eu tenha um "MyControl" em um UserControl, mesmo assim ele deve ser contado.
- Editado SammuelMiranda sexta-feira, 26 de fevereiro de 2016 21:38
Respostas
-
Sammuel,
Acho que a solução pode ser utilizar o ViewState. Ex:
protected bool IsFirstToRender() { object elemento = this.ViewState["elemento"]; return (elemento == null); }
protected override void Render(HtmlTextWriter writer) { if (this.IsFirstToRender()) { this.My1TimeAction(writer); ViewState["elemento"] = "renderizado"; } base.Render(writer); }
Links que podem ser úteis:
- Marcado como Resposta SammuelMiranda quinta-feira, 3 de março de 2016 11:50
-
Cesar, obrigado por responder.
Isso é mais ou menos o que eu estava testando, mas tem um problema. o "ViewState" acessado por este controle é DELE. Para isso funcionar eu teria que acessar o "ViewState" da página em que o controle está alocado. Porque se eu tiver 2 controles do tipo "MyControl" cada um deles vai executar a ação.
O objetivo não é impedir que a ação aconteça mais de uma vez (ou seja, só na primeira vez que o controle renderiza); o objetivo é executar apenas 1 vez, por renderização, apenas no primeiro controle.
Se a página fosse:
public class MyPage : Page { protected MyControl controle1; protected MyControl controle2; protected MyControl controle3; protected MyControl controle4; protected MyControl controle5; protected MyControl controle6; protected MyControl controle7; protected MyControl controle8; }
A cada vez que fosse renderizada a página (mesmo postback, etc) a função "IsFirstToRender" deveria retornar verdadeiro para o "controle1", e falso para todos os outros ("controle2" ao "controle8"). Entende?
Editado:
Acabei de pesquisar um pouco mais e achei um tópico que pode ser a solução. Alguém postou no StackOverflow (why-cant-i-access-page-viewstate-in-usercontrol). Acredito que isso resolve. A variável declarada no HttContext, assim quando o Request terminar ela será destruída. Meu dilema era que eu precisava de uma variável "static" mas que o escopo não fosse o programa e sim o "request". Isso se adequa.
- Editado SammuelMiranda quinta-feira, 3 de março de 2016 11:49 Possível Solução
- Marcado como Resposta SammuelMiranda quinta-feira, 3 de março de 2016 11:50
Todas as Respostas
-
-
Estive procurando uma variável (ou um lugar que eu possa criar uma variável) que tenha como escopo até o Response ser completado - não achei nada; imagino que isso resolveria meu problema pois, o que preciso é uma variável estática "Integer" para saber quantos controles já renderizaram (do tipo e derivados) - se fosse um programa Windows Forms.
Mas como as variáveis estáticas tem como escopo o aplicativo, independente das sessões, páginas etc - preciso que uma variável que seja aplicada aquela Request/Response. Alguma ideia?
-
-
Sammuel,
Acho que a solução pode ser utilizar o ViewState. Ex:
protected bool IsFirstToRender() { object elemento = this.ViewState["elemento"]; return (elemento == null); }
protected override void Render(HtmlTextWriter writer) { if (this.IsFirstToRender()) { this.My1TimeAction(writer); ViewState["elemento"] = "renderizado"; } base.Render(writer); }
Links que podem ser úteis:
- Marcado como Resposta SammuelMiranda quinta-feira, 3 de março de 2016 11:50
-
Cesar, obrigado por responder.
Isso é mais ou menos o que eu estava testando, mas tem um problema. o "ViewState" acessado por este controle é DELE. Para isso funcionar eu teria que acessar o "ViewState" da página em que o controle está alocado. Porque se eu tiver 2 controles do tipo "MyControl" cada um deles vai executar a ação.
O objetivo não é impedir que a ação aconteça mais de uma vez (ou seja, só na primeira vez que o controle renderiza); o objetivo é executar apenas 1 vez, por renderização, apenas no primeiro controle.
Se a página fosse:
public class MyPage : Page { protected MyControl controle1; protected MyControl controle2; protected MyControl controle3; protected MyControl controle4; protected MyControl controle5; protected MyControl controle6; protected MyControl controle7; protected MyControl controle8; }
A cada vez que fosse renderizada a página (mesmo postback, etc) a função "IsFirstToRender" deveria retornar verdadeiro para o "controle1", e falso para todos os outros ("controle2" ao "controle8"). Entende?
Editado:
Acabei de pesquisar um pouco mais e achei um tópico que pode ser a solução. Alguém postou no StackOverflow (why-cant-i-access-page-viewstate-in-usercontrol). Acredito que isso resolve. A variável declarada no HttContext, assim quando o Request terminar ela será destruída. Meu dilema era que eu precisava de uma variável "static" mas que o escopo não fosse o programa e sim o "request". Isso se adequa.
- Editado SammuelMiranda quinta-feira, 3 de março de 2016 11:49 Possível Solução
- Marcado como Resposta SammuelMiranda quinta-feira, 3 de março de 2016 11:50