domingo, 11 de marzo de 2012

Tiempo de Diseño en Controles

Continuando con nuestro pequeño tutorial. del post anterior sobre la creacion de un custom server controls para ASP.Net vamos hablar del tiempo de diseño o modo de diseño.Nos referimos  a cuando usamos el diseñador de Visual Studio para colocar y modificar nuestros controles.

Cuando estamos trabajando en el diseñador con nuestros controles debemos estar consientes que éstos se muestran o dibujan utilizando el método Render del mismo. Hay casos en los que accedemos a variables o recursos que únicamente están disponibles en tiempos de ejecución. Esto puede provocar que el control no se pueda dibujar de forma correcta.

En el caso de nuestro tutorial. cuando cambiamos la propiedad DisplayFormat de nuestro Label personalizado por algún valor  distinto  a "NoFormat" se nos muestra la Exception tal y como esta previsto para el tiempo de ejecución en el método Render:


Para controlar este comportamiento se pueden emplear varias técnicas. La Primera y más natural es que la clase Control (de la que heredan los webcontrols como el Label o TextBox) expone la propiedad DesignMode.la cual es verdadera cuando se está en tiempo de diseño por lo cual es muy sencillo hacer lo siguiente:
protected override void Render(HtmlTextWriter writer)
{
    if (this.DesignMode)
    {
        //Estoy en tiempo de diseño
    }
        else
    {
        //Estoy en tiempo de Ejecución
    }
    base.Render(writer);
}

También se puede usar HttpContext.Current. Si éste se encuentra nulo entonces quiere decir que se esta en diseño. Por lo que se puede crear una variable booleana que verifique si es o no null de la siguiente manera
private bool inDesignMode = (System.Web.HttpContext.Current == null);

Y finalmente se puede usar igual que DesignMode del primer segmento de código. Aplicando esto a nuestro método Render nos quedaría de la siguiente manera
protected override void Render(HtmlTextWriter writer)
{ 
    try
    {
        if (inDesignMode)
        {
            _displayformat = DisplayFormat.NoFormat;
        }

        if (Text.Length > 0)
        {
            switch (_displayformat)
            {
                case (DisplayFormat.FinancialFormat):

                    Text = Text.Replace('(', '-').Replace(")", string.Empty);
                    string cerosdecimales = ConvertirACerosDecimales(_numeroDecimales);
                    decimal montotexto = Convert.ToDecimal(Text);
                    string formato = "{0:#,##" + cerosdecimales + ";(#,##" + cerosdecimales + ");0.00}";
                    this.Text = string.Format(formato, montotexto);
                    if (montotexto < 0)
                    {
                        this.ForeColor = System.Drawing.Color.Red;
                    }
                    break;
                case (DisplayFormat.MountFormat):
                    string formatoMonto = "{0:N" + _numeroDecimales.ToString() + "}";
                    Text = string.Format(formatoMonto, Convert.ToDecimal(Text));
                    break;
            }
        }       
    }
    catch (Exception ex)
    {
        Text = "Se ha producido un error aplicando el formato: " + ex.Message;
    }
    finally
    {
        base.Render(writer);
    }
}

Por lo que ya no importa cuando le cambiamos el valor a la propiedad DisplayFormat en el Diseñador siempre se mostrará el mismo diseño sin afectar el comportamiento real cuando se encuentre en tiempo de ejecución:

Otra cosa a tomar en cuenta en el tiempo de diseño es que ocasionalmente,.cuando se realizan cambios a controles que se encuentran dentro de un UpdatePanel y volvemos a la vista de diseño esta se puede desconfigurar mostrando una vista con un error similar al siguiente:

O ingles sería 'UpdatePanel' could not be set on property 'ContentTemplate' Cuando esto sucede lo que único que podemos hacer es cerrar el Visual Studio e ir a la ruta de de los archivos temporales (por lo general [WINDOWS]\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files) y borrar las carpetas de nuestros proyectos. Una vez hecho esto podemos reabrir Visual Studio y nuestra solución y el problema debería quedar resuelto.

0 comentarios: