viernes, agosto 05, 2011

NETCF: Crear un UserControl que acepte otros controles en tiempo de diseño

Hoy me encontre con un problema que, aunque al principio me confundio bastante, despues logre entender la logica del asunto y la razon de porque lo que queria hacer no iba a funcionar.

El tema es que queria crear un UserControl que me sirviera de container para almacenar otros objetos en un form, muy al estilo de lo que haria un control tipo Panel, pero con la ventaja de estar adaptado a una funcion especifica. Para tal efecto procedi a crear el UserControl, configure su apariencia, tamano, eventos, funcionalidad, etc.

Luego instancie un par de estos nuevos controles en un form de .NET CF y me dedique a poner algunos controles en cada uno de mis controles personalizados. La idea basicamente era que el form mostraria primero uno de los UserControl, conjuntamente con su contenido, y al pulsar un boton en el UserCOntrol1, se activaria el UserControl2 con su contenido particular.

Pero no funciono. Luego de varias pruebas me di cunta que el problema era que los controles que cree "supuestamente" dentro de los UserControls estaban realmente asociados al Form directamente.

Para los que vienen de VFP, es el mismo caso que pasaria si se creara un control basado en la clase Control en lugar de Containar: el control como tal no seria capaz de contener otros objetos en tiempo de diseno, aun cuando la clase Control es en container.

Fue entonces que me di cuenta que lo que yo queria era un control basado en UserControl pero que se comportara como un Panel. Despues de mucho buscar, encontre este post que indicaba como lograrlo.

Basicamente lo que se hace es indicarle al VS que use el Designer asociado a la clase Panel, como Designer de nuestro UserControl. De esta forma VS trata a nuestro control como si fuera un Panel (permitiendole contener otros objetos) pero en tiempo de ejecucion el control se comportara como nuestro UserControl. El truco es incluir el siguiente codigo en el archivo DesignTimeAttributes.xmta:

  <Class Name="SuNameSpace.SuUserControl;>
    <DesktopCompatible>true</DesktopCompatible>
    <Designer>
      <Type>
        Microsoft.CompactFramework.Design.WindowsCE.PanelDesigner, Microsoft.CompactFramework.Design.WindowsCE, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, Custom=null
      </Type>
    </Designer>
  </Class>