Custom Control II

En el artículo anterior Custom Control I ya vimos como empezar a crear un control compuesto y de que clases teníamos que heredar para dotarle de toda la funcionalidad necesaria.


Ahora seguiremos creando las propiedades para que el usuario pueda personalizar la apariencia entre otras cosas.


La primera propiedad que veremos será la de poder elegir el Nº de calendarios que queremos ver en el control.

[Bindable(true)]
[Category(«Datos»)]
[DefaultValue(1)]
[Description(» Número de Calendarios a mostrar»)]
public int Calendarios
{
get
{
object s = ViewState[«Calendarios»];
return ((s == null) ? 1 : (int)s);
}
set
{
ViewState[«Calendarios»] = value;
}
}

Como podéis comprobar es una propiedad muy simple que mantiene la información entre postbacks en el estado del control, por defecto siempre mostrará 1 calendario. Siguiendo esta técnica podremos crear otras propiedades como:




  • Nº de Filas int: Nº de filas en los que se repartirán los calendarios.


  • Fecha inicial DateTime: Fecha inicial para calcular el mes inicial del control.


  • Fechas Seleccionadas list<DateTime>: Lista de Datetimes con las fechas seleccionadas en los Calendarios.

Como se verán estas propiedades en tiempo de diseño.




Siguiendo con las propiedades crearemos otro grupo para el formato del control.

[Bindable(true)]
[Category(«Formato»)]
[DefaultValue(typeof(System.Drawing.Color), «Green»)]
[Localizable(true)]
[Description(«Color de Fondo de la fecha seleccionada»)]
public System.Drawing.Color ColorFondo
{
get
{
object s = ViewState[«ColorFondo»];
return ((s == null) ? System.Drawing.Color.Green : (System.Drawing.Color)s);
}

set
{
ViewState[«ColorFondo»] = value;
}
}



  • Titulo string: Titulo que se mostrará en la cabecera del control.


  • TxTSiguiente string: Texto para mostrar el link Siguiente.


  • ImgSiguiente string: Si preferimos podemos mostrar una imagen como botón Siguiente.


  • TxtAnterior string: Texto para mostrar el link Siguiente.


  • ImgAnterior string: Si preferimos podemos mostrar una imagen como botón Siguiente.


  • ColorFondo Color: Color de fondo de la fecha seleccionada por el usuario.


  • ColorTexto Color: Color del texto de la fecha seleccionada por el usuario.

  •  


    Como podéis comprobar es muy fácil crear nuestras propiedades que son soportadas en tiempo de diseño, el entorno nos permite trabajar con algunos tipos como Colors y enumeraciones.



    Para terminar con las propiedades de nuestro control porque no le damos la posibilidad de personalizar los estilos!!.

    private TableItemStyle selectedDayStyle;

    [Category(«Css»)]
    [DefaultValue(«»)]
    [Description(«Clase CSS día seleccionado.»)]
    [PersistenceMode(PersistenceMode.InnerProperty)]
    public TableItemStyle SelectedDayStyle
    {
    get
    {
    if (selectedDayStyle == null)
    selectedDayStyle = new TableItemStyle();

    if (IsTrackingViewState)
    ((IStateManager)selectedDayStyle).TrackViewState();

    return selectedDayStyle;
    }
    }


    Para esta propiedad utilizamos la Clase TableItemStyle que representa las propiedades de estilo de un elemento de un control que se representa como un TableRow o un TableCell.


     


    Para dotar de todos los estilos necesarios a nuestro control crearemos estas propiedades:



  • OtherMonthDayStyleEstilo de los días que no pertenecen al mes actual.


  • SelectedDayStyle: Estilo de los días seleccionados.


  • WeekendDayStyle: Estilo para los días de fin de semana.


  • TodayDayStyle: Estilo para el día de hoy.



  • DayHeaderStyle: Estilo para los nombres de los días de la semana.



  • SelectorStyle: Estilo para los selectores de semana y de mes.


  • DayStyle: Estilo para los días del calendario.


  • TitleStyle: Estilo para la cabecera del control. 

  • Bueno, ya tenemos todos los controles secundarios que necesitamos y las propiedades para el buen funcionamiento del control, pero aún nos quedan un par de cosas que podemos hacer para que nuestro calendario funcione al 100%.


    Por eso lo dejaremos para el siguiente artículo, espero que os haya gustado.


    User Control I    –    User Control II  –  User Control III


    ** CrossPosting Desde http://www.lonetcamp.com ***


     

    Custom Control I


    Me da la sensación que estamos muy acostumbrados a buscar recursos en Internet  y no pararnos a pensar que a veces no están complicado adaptar los controles existentes a nuestras necesidades.


    Basándome en esta suposición publicare un par de artículos para explicar como crear un control personalizado  que he necesitado en un proyecto.

     

    Al final publicare el proyecto para que podáis probar.


    El control.


    Para una aplicación de reservas por Internet necesitábamos tener un calendario lo suficientemente adaptable para su reutilización.
    Por ejemplo el uso de dos calendarios “el típico desde hasta” o el uso de n calendarios para entrar un rango de Temporadas.



    Primero crearé un proyecto Web para probar el control en su salsa y después crearé un proyecto de clases para el control personalizado.


     


    Crearemos una nueva clase llamada Acicalendar que nos servirá para nuestro nuevo control.


     


    [ToolboxData(«<{0}:AciCalendar runat=server></{0}:AciCalendar>»)]


     public class AciCalendar : CompositeControl


     


    Como crearemos un control compuesto por más de un control y no unos basaremos en un control en concreto heredaremos de CompositeControl que implementa la configuración básica requerida por los controles Web que contienen controles secundarios.


     


     public abstract class CompositeControl : WebControl, INamingContainer, ICompositeControlDesignerAccessor




      • WebControl: proporciona las propiedades, métodos y eventos que comparten todos los controles de servidor Web.
      • INamingContainer: Cualquier control que implemente esta interfaz, crea un nuevo espacio de nombres en el cual se garantiza que todos los atributos del Id. de controles secundarios son únicos dentro de una aplicación.
      • ICompositeControlDesignerAccessor: Proporciona una interfaz para permitir a un diseñador de controles compuestos volver a crear los controles secundarios de su control asociado en tiempo de diseño llamando al método RecreateChildControls del control en tiempo de diseño. El diseñador asociado debe derivar de CompositeControlDesigner.

    Nuestro control estará formado por: 




    • List<Calendar> LCalendarios: Una lista de Calendarios para tener un número ilimitado de calendarios contenidos en el control.


    • LinkButton lAnterior: Link para mover los calendarios para los meses anteriores.


    • ImageButton ImAnterior: Podremos elegir entre el link o una imagen para mover los calendarios a los meses anteriores.


    • Label lTitulo: Título que mostrará el control.


    • LinkButton lSiguiente: Link para mover los calendarios para los meses siguientes.


    • ImageButton ImSiguiente: como antes podemos elegir entre un link o una imagen para navegar entre los calendarios.

    Una vez que tenemos la clase preparada podemos empezar a crear nuestro control, para eso sobrescribimos el método CreateChildControls que es el encargado de crear los controles contenidos por el nuestro.


     



        this.Controls.Clear();

     

        #region Variables

     

          lTitulo = new Label();


          lSiguiente = new LinkButton();


          ImSiguiente = new ImageButton();


          lAnterior = new LinkButton();


          ImAnterior = new ImageButton();


          LCalendarios = new List<Calendar>();

     

        #endregion Variables


     


    Como podéis comprobar lo primero que hacemos es limpiar la colección de controles secundarios e instanciar los nuevos.


     


    Seguidamente comenzamos con la navegación  y el título del control.


     


    #region Título

     

    lTitulo.Text = this.Titulo;


    lAnterior.Text = this.TxtAnterior;


    lAnterior.Click += new EventHandler(lAnterior_Click);


    ImAnterior.ImageUrl = this.ImgAnterior;


    ImAnterior.ImageAlign = ImageAlign.Baseline;


    ImAnterior.Click += new ImageClickEventHandler(ImgAnterior_Click);

     

    lSiguiente.Text = this.TxtSiguiente;


    lSiguiente.Click += new EventHandler(lSiguiente_Click);


    ImSiguiente.ImageUrl = this.ImgSiguiente;


    ImSiguiente.ImageAlign = ImageAlign.Baseline;


    ImSiguiente.Click += new ImageClickEventHandler(ImgSiguiente_Click);

     

    #endregion Título


     


    Dos cosas destacan de este código, la primera es que utilizaremos propiedades que veremos más adelante para formatear nuestros controles secundarios.


     


    lTitulo.Text = this.Titulo;


     


    Y la segunda es que enlazamos el evento Click del control secundario a un evento del control.


     


    lAnterior.Click += new EventHandler(lAnterior_Click);


     


    Porque tenemos que hacer esto???


     


    [Category(«AciCalendar»)]


    [Description(«Evento de anterior posterior mes.»)]


    public event EventHandler MonthChanged;

     

    protected void OnMonthChanged(EventArgs e)


    {


        if (MonthChanged != null)


        {


            MonthChanged(this, e);


        }


    }

     

    private void lSiguiente_Click(object sender, EventArgs e)


    {


       this.FechaInicial = this.FechaInicial.AddMonths(this.Calendarios);


       CargarCalendarios();


      


       //lanzamos el evento del control


       OnMonthChanged(EventArgs.Empty);


    }


     


     


    Como NO tenemos acceso directo a los eventos generados por los controles secundarios, tenemos dos opciones o hacer que estos eventos se propaguen a nuestro control o crear un evento nuevo en el control que sea lanzado por el evento de un control secundario. Uff!!


     


    En este caso he creado un evento nuevo MonthChanged que es lanzado cuando se hace Click en el link Siguiente. De esta forma podemos controlar cuando el usuario hace click en nuestro control para avanzar los meses necesarios en nuestro control.


     


    private void lSiguiente_Click(object sender, EventArgs e)


    {


      


       //lanzamos el evento del control


       OnMonthChanged(EventArgs.Empty);


    }


     


    Ahora seguimos con la creación de los controles secundarios 😉


     


    #region Calendarios

     

    int col = this.Calendarios / this.Filas;


    int mes = 0;

     

    for (int y = 0; y < this.Filas; y++)


    {


        for (int x = 0; x < col; x++, mes++)


        {


           #region calendario

     

           Calendar cal = new Calendar();


           cal.ShowNextPrevMonth = false;


           cal.VisibleDate = FechaInicial.AddMonths(mes);


           cal.SelectionChanged +=


           new EventHandler(this.cal_SelectionChanged);


           cal.DayRender += new DayRenderEventHandler(cal_DayRender);


           CargarFechas(cal);

     

           //le aplicamos los estilos.


           cal.CssClass = this.CssCalendario;


           cal.SelectorStyle.CopyFrom(this.SelectorStyle);


           cal.DayHeaderStyle.CopyFrom(this.DayHeaderStyle);


           cal.WeekendDayStyle.CopyFrom(this.WeekendDayStyle);


           cal.TodayDayStyle.CopyFrom(this.TodayDayStyle);


           cal.SelectedDayStyle.CopyFrom(this.SelectedDayStyle);


           cal.TitleStyle.CopyFrom(this.TitleStyle);


           cal.DayStyle.CopyFrom(this.DayStyle);


           cal.OtherMonthDayStyle.CopyFrom(this.OtherMonthDayStyle);


           cal.SelectionMode = CalendarSelectionMode.DayWeekMonth;


           cal.SelectedDayStyle.BackColor = this.ColorFondo;


           cal.SelectedDayStyle.ForeColor = this.ColorTexto;

     

           LCalendarios.Add(cal);


           this.Controls.Add(cal);

     

           #endregion calendario

     

    #endregion calendarios


     


    this.Controls.Add(lAnterior);


    this.Controls.Add(ImAnterior);


    this.Controls.Add(lTitulo);


    this.Controls.Add(lSiguiente);


    this.Controls.Add(ImSiguiente);


     


     


     


    Como podéis comprobar podemos elegir el Nº de columnas y el Nº de filas que queramos que utilice el control y el Nº total de calendarios a repartir.


     


    Entonces creará los calendarios necesarios, le enlaza los eventos SelectionChanged, DayRender y establecerá propiedades y estilos para los controles.


     


    Finalmente agregará el calendario a la lista de calendarios y también a la colección de controles secundarios de nuestro control.


     


    Bueno ya tenemos la base de nuestro control creado con esto, espero que os esté interesando el tema y no os haya aburrido demasiado.


     


    Dejaremos la parte final del proyecto para el siguiente artículo espero veros.


     

    **CrossPosting dede www.lonetcamp.com **

    Net Developer Group "LoNetCamp"

    Nuevo Net Developer Group para la Provincia de Tarragona !!!!!!



    Se acabaron las vacaciones y ya estamos aquí…..


    Por fin hemos creado un grupo de usuari@s para la provincia de Tarragona donde prepararemos eventos, charlas, cursos y todo lo que podamos necesitar para promover y experimentar en este gran y imparable mundo de la tecnología.


    Para comenzar ya hemos creado nuestra página web, un punto de encuentro para conocernos, charlar y preparar los eventos..


    http://lonetcamp.com/Community/


    Quien quiera entrar en el grupo será bienvenid@ y ya puede comenzar a prepararse porque estamos organizando nuestro primer evento.


    Espero veros a tod@s!!!


    P.D


    Si tienes tiempo o simplemente te apetece ser uno o una de los organizadores/as no dudes en ponerte en contacto conmigo.


     

    [Ajax.Net] Iframe Redimensionable

    Trabajar con iFrames es una tarea bastante ingrata sobre todo cuando te interesa que el contenedor se adapte al tamaño del contenido.
    Buscando por internet encontré unos ejemplos muy interesantes:



    1. El de Microsoft http://support.microsoft.com/kb/278469/es

    2. El de los foros  http://www.forosdelweb.com/showthread.php?t=510457

    Nos explican como aprovechar el evento onload del BODY para lanzar una función javaScript que recalcule el tamaño.


    Pero que pasa si la página del iFrame utiliza Ajax.Net ?????


    Pues que como ajax.net carga parcialmente la página no se lanza el evento onload de nuevo.Entonces seguí surfeando por la web y encontré otro artículo muy interesante http://netcodigo.webinfo.es/2007/02/02/controlar-llamadas-asincronas-con-aspnet-ajax/.


    Con este artículo conocí la clase PageRequestManager clase encargada de controlar el renderizado parcial de las páginas, tenemos eventos, Métodos y propiedades para proporcionarnos este servicio.      



    • PageRequestManager Class


      • Events 


        • beginRequest Event

        • endRequest Event

        • initializeRequest Event

        • pageLoaded Event

        • pageLoading Event

      • Methods


        • abortPostBack Method

        • dispose Method

        • getInstance Method

      • Properties


        • isInAsyncPostBack Property  

    Realmente muy interesante !!!


    se me ocurren un montón de utilidades posibles 😉
    Podéis obtener más información en :
    http://asp.net/ajax/documentation/live/clientreference/Sys.WebForms/PageRequestManagerClass/default.aspx


    Bueno no me desviaré del tema y seguiremos con el ejemplo.

    <asp:ScriptManager ID=»ScriptManager1″ runat=»server» EnablePageMethods=»True»></asp:ScriptManager><script type=»text/javascript»>var prm = Sys.WebForms.PageRequestManager.getInstance(); prm.add_endRequest(Redimensionar);onload = function Redimensionar(sender,art){top.window.document.getElementById(«demoFrame»).height = document.getElementById(«aspnetForm»).offsetHeight;top.window.document.getElementById(«demoFrame»).width = document.getElementById(«aspnetForm»).offsetWidth;}</script>

    1. Tenemos que activar la propiedad EnablePageMethods=»True» he instanciar la clase PageRequestManager para utilizarla.

    var prm = Sys.WebForms.PageRequestManager.getInstance();


    1. Asociamos el evento que nos interesa a una función javascript

    prm.add_endRequest(Redimensionar);


    1. Creamos el script que redimensionará el iFrame.
      Para probar el código he creado un proyecto que utiliza una página con un iframe y un update panel.
    <iframe frameborder=»0″ id=»demoFrame» marginheight=»0″         marginwidth=»0″ scrolling=»no» src=»Pagina1.aspx»> </iframe> Al clicar el botón se aplica un bucle que aumenta el tamaño de la página.

    Muy importante este ejemplo solo funciona con páginas dentro del mismo Dominio como muy bien lo explican en el primer link de Microsoft.

    Si queréis bajaros el proyecto lo podéis hacer desde este link. http://lonetcamp.com/Community/files/folders/art/entry54.aspx

    Saludos a Todos 🙂 

    October Conference 2007

    Los amigos de Málaga .NET User Group han abierto el registro gratuito para su evento de Octubre(15 y 16 de octubre 2007 – Malaga, Spain).


    Según sus propias palabras el evento es:


    La conferencia va a cubrir un amplio rango de temas, y las ponencias estarán disponibles tanto en español como en inglés. Expertos de todo el mundo van a participar durante los dos días que durará el evento. Será tu oportunidad para interactuar con tus compañeros de profesión y charlar con los ponentes durante este evento relajado.


    Los ponentes son de renombre internacional como:




    • Near Ford, Thoughtworks


    • Michael Li, InfoCan Management


    • Chad Hower, Woo-hoo


    • Dino Esposito, Solid Quality Leaning


    • Hadi Hariri, Atozed Software


    • Octavio Hernandez, Plain Concepts


    • Guillermo Som, Solid Quality Learning


    • Martin Luis Lopez, Adesis NetLife


    • José Manuel Alarcón Aguín, Krasis


    • Unai Zorrilla Castro, Plain Concepts

     Como podéis comprobar es la crem de la crem y totalmente gratis.


    Para mas información http://www.octoberconference.net


    Para registrarse http://msevents.microsoft.com/CUI/EventDetail.aspx?culture=en-US&EventID=1032348903


    Espero que nadie falte [;)]

    Nuevo vecino en la Comunidad !!!

    En realidad no soy tan nuevo [;)] pero hasta ahora no me había planteado la posibilidad de tener mi propio rinconcito.


     Pero bueno, todas las aportaciones al conocimiento común espero que sean bien acogidas por todos.


    Para empezar y para que podáis conocerme un poquito mejor os dejo un par de links a unos artículos que publiqué en elguille y que espero que aún sean útiles para todos:





    • Código de Barras

      Creación e Impresión de Código de Barras utilizando Fuentes Personalizadas ( True Type )


    Bueno espero veros pronto a todos por este sitio.