.Net, Dynamic Controls, WebControls y ViewState

Para un proyecto necesito hacer un “Custom Control” (tambien llamados a veces Server Controls o WebControls) que sea una composición de controles generados dinamicamente porque no puedo saber a priori ni la cantidad ni el tipo de controles que necesitaré. Además necesitaba que mantuvieran, estos controles dinámicos, el viewstate.

Me tropecé con un montón de trabas, así que en lugar de intentar mi problema original, comencé con casos muchos mas simples para intentar apuntar a cada problema que tenía específico. El más molesto de todos ellos era que el ViewState se perdía en cada postback.

Originalmente mi clase de prueba, que agregaba dos textbox y un botón para testear el postback era así:

public class FiltersControl : WebControl
{
    public FiltersControl() : base(HtmlTextWriterTag.Div) { }

    protected override void CreateChildControls()
    {
        TextBox text1 = new TextBox();
        TextBox text2 = new TextBox();

        Button button = new Button();
        button.Text = "Postback!";

        Controls.Add(text1);
        Controls.Add(text2);
        Controls.Add(button);
    }
}

Pero fallaba inmediatamente, sin embargo si lo heredaba de CompositeControl funcionaba perfectamente. Gracias a Lutz Roeder’s Reflector e investigando como funcionaba CompositeControl llegué a la conclusión que agregando únicamente la interfaz marcador INamingContainer se solucionaban todos los problemas, al menos en ese código tan simple.

Así que el siguiente código funciona como uno esperaría, y se puede apreciar que es idéntico al anterior, pero esta vez la clase tiene una interfaz.

public class FiltersControl : WebControl, INamingContainer
{
    public FiltersControl() : base(HtmlTextWriterTag.Div) { }

    protected override void CreateChildControls()
    {
        TextBox text1 = new TextBox();
        TextBox text2 = new TextBox();

        Button button = new Button();
        button.Text = "Postback!";

        Controls.Add(text1);
        Controls.Add(text2);
        Controls.Add(button);
    }
}

Moraleja, si implementan un control, que contiene otros controles, aún cuando saben que no habrá conflictos de nombres, o heredan de CompositeControl o lo hacen de Control (o alguna clase que herede) y marcan la clase con la interfaz INamingConteiner para no tener problemas con el ViewState


Discussion Area - Leave a Comment