El evento CellPainting del control DataGridView
Transcripción
El evento CellPainting del control DataGridView
www.dotnetmania.com nº 43 diciembre 2007 6,50 € Visual Basic • C# • ASP.NET • ADO.NET • SQL Server • Windows System dotNetManía dedicada a los profesionales de la plataforma .NET Vía libre a la creatividad El evento CellPainting del control DataGridView entrevista Catherine Heller Technical Evangelist Microsoft Corporation eventos TechEd Europe 2007 Lanzamiento de Biztalk 2006 R2 CEUS 2007 Tablet PC SDK (y II). Reconocimiento de escritura manual • Más sobre seguridad de acceso a código • Herramientas genéricas para los componentes: ficheros y recursos • Depuración en .NET. El depurador que lo depure... recibirá ayuda del CLR Laboratorio ILOG Diagrammer for .NET TodotNet@QA Silverlight. Presente y futuro Opinión Documentos o ejecutables editorial dotNetManía Dedicada a los profesionales de la plataforma .NET Vol. III •Número 43 • Diciembre 2007 Precio: 6,50 € Un codename, por favor Editor Paco Marín ([email protected]) Redactor jefe Marino Posadas ([email protected]) Editor técnico Octavio Hernández ([email protected]) Redacción Dino Esposito, Guillermo 'Guille' Som, José Manuel Alarcón, Luis Miguel Blanco y Miguel Katrib (Grupo Weboo) Empresas Colaboradoras Alhambra-Eidos Krasis Plain Concepts Raona Solid Quality Learning Además colaboran en este número Alberto Población, Daniel Seara, Javier Roldán y Rodrigo Corral. Corresponsal para América Latina Pablo Tilotta Ilustraciones Mascota (Clico): Yamil Hernández Portada: Javier Roldán Fotografía Roberto Mariscal Atención al suscriptor Pilar Pérez ([email protected]) Edición, suscripciones y publicidad .netalia c/ Thomas Edison, 4, 1406 Parque empresarial Rivas Futura 28521 - Rivas Vaciamadrid (Madrid) www.dotnetmania.com Tf. (34) 91 666 74 77 Fax (34) 91 499 13 64 Bienvenido al número 43, de diciembre de 2007, de dotNetManía. La cuenta atrás terminó y Visual Studio 2008 está listo para su fabricación (Ready To Manufacture, que dicen los anglosajones). Ésta es ya la versión final, descargable por los suscriptores de MSDN, aunque también existen versiones de evaluación y Express para el resto de clientes. Ahora toca rumorear sobre la próxima versión, de la que queda la duda de si tendrá finalmente el codename Hawaii, como se dijo en un principio. Aunque aún nos queda lejos —supuestamente hasta 2010 ó 2011—, nos podrían dar un codename fiable pronto, porque si no ¿de qué vamos a hablar?, ¿de la innombrable nueva versión de Visual Studio? Una isla o lo que prefieran, pero ¡dennos un codename, por favor! Lo que sí tiene nombre fiable es la nueva editorial de tecnologías Microsoft que acaba de nacer en España: Krasis Press. Esto es una magnífica noticia para todos los lectores castellano-hablantes. En nombre de todo el equipo de dotNetManía quiero desearles la mejor de las suertes. Ya tienen tres libros y pronto aparecerán más. Los tres han sido escritos por amigos de esta casa: José Manuel Alarcón (el padre de la criatura), Octavio Hernández, editor técnico de dotNetManía y Unai Zorrilla, colaborar habitual de esta revista. Este mes entrevistamos a una vieja conocida nuestra: Catherine Heller, Technical Evangelist de Microsoft Corp., a la que Marino Posadas ya entrevistó en 2003 en el Ave Fénix (www.elavefenix.com). Medio española, medio americana, Catherine empezó su carrera profesional en Microsoft Ibérica y lleva ya unos cuantos años desarrollando su actividad en Redmond. Actualmente está trabajando junto al equipo de Windows Live. El artículo de portada de este mes se titula “El evento CellPainting del control DataGridView. Vía libre a la creatividad”. Si quiere lograr efectos avanzados y un mayor control sobre el proceso de dibujo de las celdas, debe utilizar de forma conjunta el evento CellPainting y las clases de GDI+. Luis Miguel Blanco se lo explica con todo lujo de detalles, como siempre. Entre nuestros asuntos pendientes, Javier Roldán termina la miniserie de artículos dedicada al reconocimiento de escritura manual con Tablet PC SDK, mientras que Alberto Población publica el artículo “Más sobre seguridad de acceso a código”, una extensión de su artículo “Seguridad de acceso a código”, publicado en el número 41, de octubre de 2007. Y aún hay más, por supuesto. Espero que le guste. Imprime Gráficas MARTE ISSN 1698-5451 Paco Marín << dotNetManía Depósito Legal M-3.075-2004 3 sumario 43 Documentos o ejecutables 10-11 La documentación siempre es un aspecto que exige nuestra atención en los proyectos de software. A menudo tendemos a pensar que la mejor manera de lograr que nuestros proyectos avancen y poder mostrar ese avance es realizando la documentación adecuada, buscando el ciclo adecuado para esa documentación y estableciendo una serie de documentos como estándares. Incluso hay metodologías bastante populares que se centran en definir qué documentos se deben generar, quién es el responsable de cada documento y por qué manos debe pasar cada uno de ellos. ¿Nos olvidamos de que los documentos no se pueden ejecutar? ¿Nos olvidamos de que el propósito final de todo proceso de desarrollo es conseguir software que funciona? Entrevista a Catherine Heller 12-14 Catherine Heller es española (nacida en Madrid), de padre norteamericano, y con muchos años de estancia en los dos países. En la actualidad, trabaja como evangelista en el grupo de divulgación de Windows Live, en Redmond, y anteriormente lo había hecho en el de Visual Studio Tools for Office. Eso fue antes de pasar en Microsoft Ibérica otra buena parte de su carrera… Eventos 16-19 TechEd 2007: expectación ante un año pleno de novedades, Lanzamiento de Biztalk 2006 R2 y CEUS 2007 Tablet PC SDK (y II). Reconocimiento de escritura manual 20-26 En la primera parte de este artículo indicamos el modo de preparar el entorno de desarrollo necesario para la programación de aplicaciones capaces de aceptar tinta digital para más tarde reconocerla como escritura manuscrita. Asimismo, utilizamos los principales elementos que para este fin proporciona el Microsoft Windows XP Tablet PC Edition Software Development Kit. El evento CellPainting del control DataGridView.Vía libre a la creatividad 27-35 Cuando presentamos a nuestros usuarios un conjunto de datos mediante el control DataGridView, podemos mejorar la apariencia visual del mismo recurriendo al uso de estilos. No obstante, la mera utilización de estilos resulta escasa si nuestras pretensiones pasan por lograr efectos avanzados y un mayor control sobre el proceso de dibujo de las celdas. Es por ello que el empleo combinado del evento CellPainting, perteneciente a este control, junto al conjunto de clases de GDI+ se va a convertir en un poderoso recurso a nuestro alcance. Más sobre seguridad de acceso a código 36-39 En una entrega anterior (dotNetManía nº 41) presentamos los fundamentos de la Seguridad de acceso a código (Code Access Security, CAS) en .NET Framework, y describimos cómo el CLR determina los permisos del código y cómo se pueden manipular desde las herramientas administrativas los permisos concedidos a cada ensamblado. En esta entrega veremos cómo se pueden solicitar, manipular y limitar estos permisos desde dentro de nuestro código. Herramientas genéricas para los componentes: ficheros y recursos 40-42 Siguiendo con la idea de las generalizaciones en componentes expuesta en el número anterior, en este artículo veremos algunos otros ejemplos que pueden resultarle interesantes. Depuración en .NET. El depurador que lo depure... recibirá ayuda del CLR 43-49 La depuración es una de esas cosas que todos hacemos, o deberíamos hacer, y que a nadie le gusta tener que hacer; no porque no sea necesaria, sino porque al final terminabas fatal de los nervios cuando la depuración la realizabas con versiones anteriores de Visual Studio para .NET; por suerte, esto ya no es así con Visual Studio 2005. En esta serie de dos artículos mostraremos las principales posibilidades que este último entorno pone a nuestro alcance para facilitarnos la depuración de nuestros programas. dnm.todotnet.qa 50-52 Silverlight. Presente y futuro. dnm.laboratorio.net 53-55 ILOG Diagrammer for .NET dnm.comunidad.net 56 dnm.biblioteca.net 57 Microsoft Expression Web Plain & Simple C# 3.0 y LINQ dnm.desvan 58 <<dotNetManía noticias noticias noticias noticias noticias 6 Visual Studio 2008 listo para fabricarse El lunes 19 de noviembre, Microsoft anunció que Visual Studio 2008 y .NET Framework 3.5 han pasado a fabricación. Al mismo tiempo, la versión definitiva ha sido puesta a disposición de los suscriptores MSDN para su descarga. Con más de 250 nuevas características, Visual Studio 2008 incluye mejoras significativas en cada una de sus ediciones, desde Visual Studio Express hasta Visual Studio Team System. Los desarrolladores de todos los niveles podrán disponer de un entorno integrado consistente, seguro y confiable para desarrollar aplicaciones para las plataformas más actuales: la Web, Windows Vista, Windows Server 2008 y 2007 Office System. Visual Studio 2008 habilita la visión de Microsoft acerca de las aplicaciones cliente inteligentes, permitiendo a los desarrolladores crear de manera rápida aplicaciones conectadas que ofrezcan las experiencias de usuario más ricas y de más alta calidad. Con Visual Stu- dio 2008, las empresas encontrarán más fácil que nunca capturar y analizar la información para tomar decisiones de negocio correctas. Visual Studio 2008 permitirá a las empresas de cualquier tamaño desarrollar con una alta productividad aplicaciones más seguras y confiables que aprovechen las bondades de Windows Vista y 2007 Office System. Visual Studio 2008 introduce avances significativos para los desarrolladores en tres áreas fundamentales: • Desarrollo rápido de aplicaciones. • Colaboración efectiva de equipos. • Experiencias de usuario avanzadas. Visual Studio 2008 ofrece herramientas de desarrollo, posibilidades de depuración y funcionalidades de trabajo con bases de datos avanzadas e innovadoras para facilitar la creación de aplicaciones de las aplicaciones del mañana para una amplia variedad de plataformas. Incluye mejoras tales como diseñadores visuales para un desarrollo más rápido para .NET Framework 3.5, mejoras sustanciales en las herramientas para el desarrollo de aplicaciones Web potenciadas por la tecnología AJAX, y mejoras en los lenguajes de programación (concretamente las Consultas integradas en los lenguajes —LINQ—) que aceleran el desarrollo de aplicaciones que accedan a datos de cualquier naturaleza. Silverlight 1.1 Tools Alpha para Visual Studio 2008 disponible para descarga Microsoft ha anunciado recientemente una versión actualizada de Silverlight 1.1 Tools Alpha que trabaja con la versión final de Visual Studio 2008. Éste es un add-on para desarrollar aplicaciones Silverlight usando los lenguajes de .NET. Esta versión tiene las mismas características que el add-on de Silverlight Tools Alpha que estaba disponible previamente para la beta 2 de Visual Studio 2008; simplemente ha sido actualizada para trabajar con la versión final de Visual Studio 2008. Estas características incluyen plantillas para los lenguajes .NET, así como intellisense en code-behind, edición y generación de código XAML, soporte de depura- ción y compatibilidad e integración con proyectos Expression Blend. La próxima preview de Silverlight sí incluirá muchas nuevas características, así como significativas mejoras. Puede encontrar tutoriales quickstart que detallan cómo utilizar estas características aquí: http://silverlight.net/QuickStarts/Start. Puede descargar el add-on desde: http://www.microsoft.com/downloads/details.aspx?FamilyId=25144C27- 6514-4AD4-8BCB-E2E051416E03& displaylang=en. Más información : http://weblogs. asp.net/scottgu. Los desarrolladores podrán aprovechar todos esos marcos de trabajo tanto para el lado del cliente como para el lado del servidor para crear aplicaciones Web centradas en el cliente que se integren con cualquier proveedor de datos en el servidor, se ejecuten bajo cualquier navegador y tengan acceso total a los servicios de ASP.NET y a la plataforma Microsoft. Desarrollo rápido de aplicaciones Para ayudar a los desarrolladores a crear software moderno, Visual Studio 2008 ofrece nuevas características de acceso a datos como LINQ, que harán más sencillo el desarrollo de aplicaciones capaces de analizar información y tomar decisiones a los programadores individuales. Visual Studio 2008 ofrece además la posibilidad de generar código para diferentes versiones de .NET Framework desde dentro del propio entorno. Los desarrolladores podrán crear aplicaciones para .NET Framework 2.0, 3.0 ó 3.5, por lo que podrán dar soporte a una amplia gama de proyectos desde el mismo entorno integrado. Experiencia de usuario revolucionaria Visual Studio 2008 ofrece a los desarrolladores nuevas herramientas que aceleran la creación de aplicaciones conectadas que funcionen sobre las plataformas más reciente, incluyendo la Web, Windows Vista, Office 2007, SQL Server 2008 y Windows Server 2008. Para la Web, ASP.NET AJAX y otras nuevas tecnologías permitirán a los desarrolladores crear una nueva generación de experiencias eficientes, interactivas y personalizadas. Colaboración efectiva de equipos Visual Studio 2008 ofrece características expandidas que ayudan a mejorar la colaboración en los equipos de desarrollo, incluyendo herramientas que ayudan a integrar a los profesionales de bases de datos y los diseñadores gráficos en el proceso de desarrollo. Utilizar Microsoft .NET Framework 3.5 .NET Framework 3.5 habilita el desarrollo de aplicaciones conectadas que ofrezcan experiencias de usuario impactantes, ofreciendo los bloques prefabricados para resolver problemas de programación comunes. .NET Framework 3.5 ha sido creado incrementalmente a partir de .NET Framework 3.0, incluyendo múltiples novedades y mejoras en áreas como la librería de clases base, Windows Workflow Foundation, Windows Communication Foundation, Windows Presentation Foundation y Windows Card Space. Conjuntamente, Visual Studio y .NET Framework reducen la necesidad de escribir código de bajo nivel, reduciendo el tiempo de desarrollo y permitiendo a los desarrolladores concentrarse en resolver sus problemas de negocio. Puede descargarlo desde: http://msdn. microsoft.com/subscriptions. Liberado Microsoft Visual Studio 2008 SDK 1.0 El SDK de Visual Studio 2008 (versión 1.0) incluye herramientas, documentación y ejemplos para permitir a los desarrolladores crear, probar y desplegar extensiones de Visual Studio 2008. También se puede utilizar el SDK para crear entornos integrados personalizados basados en el nuevo Visual Studio 2008 Shell. Estos productos abren una nueva era en la extensibilidad de Visual Studio. Los desarrolladores podrán a partir de ahora utilizar el SDK no solo para crear aplicaciones que extiendan a Visual Studio, sino además para distribuir herramientas y aplicaciones libres de royalties. El modo aislado de VS 2008 Shell El modo aislado de Visual Studio Shell ofrece los fundamentos sobre los cuales los desarro- lladores pueden crear sus propios entornos integrados que funcionen en paralelo con Visual Studio. Utilizar este modo permitirá acelerar el desarrollo de herramientas de desarrollo propias, ya que será posible aprovechar el núcleo del entorno integrado de Visual Studio y concentrarse en los problemas específicos de la herramienta en desarrollo. propio. Cualquier herramienta o lenguaje que se ejecute dentro de Visual Studio Shell en modo integrado ejecutará conjuntamente con Visual Studio 2008 (Estándar o superior) si éste está instalado en la misma máquina. Utilizar este modo hará posible que Visual Studio no sea un prerrequisito en las máquinas de los usuarios que utilicen la herramienta o lenguaje. El modo integrado de VS 2008 Shell Novedades clave en el VS 2008 SDK El modo integrado de Visual Studio Shell ofrece los fundamentos sobre los cuales los desarrolladores pueden integrar sus propias herramientas y lenguajes de programación dentro de Visual Studio. El shell de modo integrado no contiene ningún lenguaje de programación, por lo que constituye la base perfecta para desplegar un entorno de desarrollo para un lenguaje • Soporte de desarrollo para VS Shell. • Mejoras en DSL Tools. • Soporte de desarrollo y pruebas para paquetes de extensión de Visual Studio en C++, C# y Visual Basic. • Nuevos ejemplos y documentación en diversas áreas. • Soporte para Windows Vista. <<dotNetManía Conjuntamente con la salida deVisual Studio 2008, Microsoft ha puesto a disposición de los usuarios el SDK de Visual Studio 2008, así como los redistribuibles del nuevo Visual Studio 2008 Shell. 7 << dnm.directo.noticias Microsoft SQL Server 2008 CTP de noviembre Cursos diciembre 2007 Microsoft anunció en el pasadoTechEd IT de Barcelona la nueva CTP (Community Technical Preview) de noviembre de SQL Server 2008, la penúltima antes de la versión RTM (Ready To Manufacture). Alhambra-Eidos lanza sus cursos de diciembre Esta edición de SQL Server 2008 trae una cantidad significativa de nuevas funcionalidades, incluyendo compatibilidad con Windows Vista y Windows Server 2008, así como nuevas características como Resource Governor, Backup Compression y Transparent Data Encryption. Esta CTP también incluye nuevas mejoras en el área de Business Intelligence tales como Design Alerts, Block Computation, Enhaced Report Designer con nuevas visualizaciones e integración con 2007 Microsoft Office System. Ésta también es la primera CTP que ayuda a los clientes a cargar y consumir cualquier tipo de datos, incluyendo el nuevo tipo FileStream para documentos no estructurados, y que ofrece soporte para el almacenamiento de datos geoespaciales, que puedan ser utilizados por aplicaciones de localización en el espacio. Compañías como Barrodale Computing Services (BCS) Ltd., Environmental Systems Research Institute Inc., I.S. Consulting Inc., Manifold y SpatialPoint han anunciado su intención de sacar aplicaciones con el soporte de datos geoespaciales en SQL Server 2008. Para recibir recursos de SQL Server 2008 específicamente seleccionados para profesionales TI, vaya a http://go.microsoft.com/fwlink/?LinkID=103187 y para desarrolladores, vaya a http://go.microsoft.com/fwlink/?LinkIsD=103186. Puede probar también la versión CTP de SQL Server 2008 Express Edition. Es una edición de SQL Server 2008 gratuita y totalmente funcional. SQL Server 2008 Express soporta 1 CPU, 1 Gb de RAM y bases de datos de hasta 4Gb. Puede descargarse desde: http://www. microsoft.com/downloads/details.aspx?FamilyId=3BF4C5CA-B905-4EBC-89011D4C1D1DA884&displaylang=en. Alhambra-Eidos, empresa especializada en facilitar soluciones a las necesidades empresariales en el ámbito de las Tecnologías de la Información y las Comunicaciones, lanza para diciembre su calendario de formación técnica dirigida a profesionales. En formato blended, que combina la formación presencial tradicional con los avances de la variedad online, Alhambra-Eidos ha programado las siguientes sesiones formativas para el mes de noviembre: Del 10 al 19 de diciembre de 2007 • Sharepoint Services y MOSS 2007 • Seguridad en redes Cisco Del 11 al 20 de diciembre de 2007 • MCTS SQL 2005 Las horas presenciales se impartirán en las aulas de: Alhambra-Eidos c/Albasanz, 16 (Madrid) Para más información, contacte con Alhambra-Eidos en el teléfono 902 313 505 o visite la Web: www.alhambra-eidos.es <<dotNetManía Feed your brain 8 Feed your brain (alimenta tu cerebro) es la frase elegida como eslogan de una nueva editorial: Krasis Press, que recientemente presentó su nuevo proyecto especializado en tecnologías Microsoft en la sede de Microsoft Ibérica, en Madrid, sumándose así a Netalia –editora de esta revista– en la edición de este tipo de contenidos. Nacida hace siete años, Krasis es un partner de Microsoft en desarrollo de productos Web y formación. La editorial nace a raíz de una de sus áreas de actividad, campusMVP, iniciativa en formación online cuyo factor diferencial es que todos los cursos son creados y tutelados por MVP (Most Valuable Professional). MVP es un galardón que Microsoft concede anualmente a los profesionales más destacados de cada país. Actualmente hay 12 MVP españoles integrados en este proyecto. Krasis Press nace para paliar la falta de información sobre tecnologías muy nuevas y el exceso en las más maduras, y como alternativa a la poca variedad de libros especializados. Con distribución nacional, venta directa a través de www.krasis.com y www.dotnetmania.com y venta cruzada con los cursos, Krasis está en negociaciones para la comercialización en Lationoamérica y EEUU en castellano. La compañía prepara además traducciones al inglés para la venta en EEUU a través de Amazon. En la actualidad cuenta con tres obras en el mercado: “Modelando procesos de negocio con Workflow Foundation”, de Unai Zorrilla Castro; “C# 3.0 y LINQ”, de Octavio Hernández Leal y “Programación Web con Visual Studio y ASP.NET 2.0”, de José Manuel Alarcón Aguín. Dirigidas a programadores, personas interesadas en la tecnología, centros académicos o de formación y universidades, se presentan en edición de lujo, en tapa dura y con distintivas frutas en sus portadas, que se corresponden con el lema de su proyecto educativo: Feed your brain. opinión Rodrigo Corral Documentos o ejecutables Rodrigo Corral es MVP y MCPD y uno de los fundadores de Plain Concepts, donde colabora como arquitecto de software. Además trabaja en Sisteplant como líder técnico en un proyecto desarrollado sobre .NET 3.0 utilizando Scrum como metodología de desarrollo. También administra Geeks.ms. Además, Rodrigo es tutor de campusMVP. Su blog es http://geeks.ms/blog/ rcorral. La documentación siempre es un aspecto que exige nuestra atención en los proyectos de software. A menudo tendemos a pensar que la mejor manera de lograr que nuestros proyectos avancen y poder mostrar ese avance es realizando la documentación adecuada, buscando el ciclo adecuado para esa documentación y estableciendo una serie de documentos como estándares. Incluso hay metodologías bastante populares que se centran en definir qué documentos se deben generar, quién es el responsable de cada documento y por qué manos debe pasar cada uno de ellos. ¿Nos olvidamos de que los documentos no se pueden ejecutar? ¿Nos olvidamos de que el propósito final de todo proceso de desarrollo es conseguir software que funciona? << A menudo, de la documentación que mantenemos durante el desarrollo solo un pequeño porcentaje tiene valor para el cliente. Es cierto que habitualmente hemos de entregar cierta documentación, manuales de operación, de administración o de usuario; esta documentación tiene un claro valor. Este tipo de documentación se debe tratar como cualquier otro entregable. En el fondo, ésta es la única documentación que es realmente imprescindible, la que el destinatario del software necesita, aquella por la que, hipotéticamente, estaría dispuesto a pagar. Minimizar la documentación que no aporta nada a nuestros clientes, que solo sirve para soportar nuestro proceso de desarrollo, y sobre todo el coste de mantenerla, debe ser uno de nuestros objetivos. El avance de los proyectos de software es algo que siempre ha preocupado a todos los implicados en los mismos. Es algo sobre los que nuestros clientes centran su interés y algo que, como gestores de proyectos, necesitamos comunicar. Tradicionalmente hemos abordado esta necesidad de mostrar el progreso mediante el uso de diferentes documentos o artefactos. Todos los que hemos tenido que mantener actualizado “el project” del proyecto sabemos lo difícil que esto es. Es tan difícil, que rara vez se hace con la disciplina que requiere, de tal modo que habitualmente este tipo de aproximación no proporciona los resultados esperados. El enfoque tradicional de mostrar el avance de los proyectos mediante documentos es algo que no funciona bien. Nuestros clientes han descubierto que los documentos rara vez nos muestran el avance real de un proyecto. Es muy posible haber trabajado mucho y tener una gran cantidad de documentación sobre un proyecto y estar a años luz de que quien financia el proyecto pueda obtener valor. ¿Quién no conoce algún proyecto en el que tras muchos meses de desarrollo lo único que había es un montón de documentos? Los documentos por sí mismos no aportan ningún retorno de la inversión. No se puede hacer nada para obtener valor para tu negocio solamente con la documentación relacionada con un proyecto de software. Solo el software que pueden ejecutar y utilizar es susceptible de crear valor para nuestros clientes. Solo el software que funciona debe ser la medida del progreso de los proyectos de desarrollo. Asumir esto nos obliga a asumir que tendremos que entre- << dnm.opinión gar software con frecuencia a nuestros clientes, que tendremos que reaccionar de manera ágil al feedback que nos proporcionen y que a cambio ellos obtendrán de manera temprana un retorno para su inversión. Debemos ser muy tacaños con el esfuerzo que ponemos en nuestra documentación; si no, corremos el riesgo de ver que todos aquellos requisitos, por poner un ejemplo, que tan detalladamente documentamos sobre el sistema de gestión que nuestro cliente quiere, son papel mojado porque han comprado una nueva unidad de negocios. Y nosotros ya hemos hecho un gasto del que difícilmente obtendremos algún retorno. La documentación en los proyectos de software pierde su relevancia y se queda obsoleta muy rápidamente, haciendo que mantenerla actualizada sea muy costoso. A menudo cometemos el error de tratar de sustituir la comunicación fluida por documentación, y cuando hacemos esto, estamos introduciendo costes e inflexibilidades en nuestro proceso de desarrollo. Otro aspecto del desarrollo de software que nos lleva a generar documentación es la necesidad de mantener los sistemas que desarrollamos. Se suele pensar que la documentación detallada del sistema nos va a evitar un montón de quebraderos de cabeza. Pero esto solo es cierto si esa documentación cumple la premisa de estar actualizada. Cuando un desarrollador encuentra una línea en la documentación que no es correcta o no está actualizada, rápidamente pierde la confianza y vuelve su vista a la única fuente de verdad absoluta: el código fuente. Esto nos lleva a la situación de que solo la documentación que se genera directamente desde el código fuente de manera automatizada tiene verdadero valor. El código es la única fuente de verdad absoluta sobre un proyecto de software a nivel de detalle, y el nivel de detalle es el único útil para modificar, extender o mantener un sistema en producción. La documentación directamente asociada al código fuente o embebida en él (comentarios que permitan generar documentación, por ejemplo, con NDoc, JDoc o similares) o aquella que se genera de manera automática desde el mismo (por ejemplo, diagramas de clases que solo son otra vista del código) es la que más valor tiene, pues evoluciona y se mantiene en paralelo al código fuente y siempre está actualizada. Otra documentación que no está directamente relacionada con el código fuente y que es de gran utilidad, si no imprescindible, es la relativa a arquitectura. Es necesario que un nuevo desarrollador o aquel que resucita el proyecto tras un tiempo puedan comprender qué decisiones de alto nivel guiaron el desarrollo. Esta documentación sirve para comprender por qué se tomaron determinadas decisiones que no se cambian con facilidad a lo largo del proyecto y proporciona una primera aproximación de alto nivel. La arquitectura de una aplicación no suele cambiar a menudo; lo que cambia más frecuentemente es la implementación, el código. Esta documentación es simple de mantener, porque es mucho más estática que la de diseño detallado. A menudo nos centramos en documentar olvidando que la principal fuente de información sobre qué hace una pieza de software está en el nombre de los componentes, de las clases y de las funciones. La principal documentación con la que contamos es el estilo de nomenclatura, la coherencia a la hora de nombrar cosas y una arquitectura general coherente. Establecer un lenguaje común, la nomenclatura y el estilo que va a guiar del desarrollo es más valioso que cualquier documentación. Mucha documentación puede emanar de una serie de patrones que se repiten a lo largo del proyecto, tanto a nivel arquitectónico como de diseño, y estos patrones donde viven es en el código. Buscando valor para el cliente, cada vez más proyectos deciden mantener una base de conocimiento sobre nuestro proyecto, basada en artículos cortos y con ejemplos, tipo knowledge base, sobre los que se pueda realizar búsquedas fácilmente. Por eso se están popularizando tanto como repositorios de información sobre proyectos los wikis: no imponen una estructura, son ágiles de mantener, fácilmente actualizables, fácilmente buscables y soportan muchos tipos diferentes de contenido. También se tiende cada vez más a sustituir la documentación por la refactorización: si una pieza de software es compleja, tenemos dos posibles estrategias a la hora de hacerla entendible. La primera es documentarla; la segunda es, a base de refactorización y de mejorar el diseño, simplificarla para hacerla más clara. Se puede ganar mucho en la legibilidad de nuestro software simplemente eligiendo buenos nombres, evitando las funciones enormes, limpiando las variables no utilizadas… La ventaja de este enfoque es que mejora objetivamente el software, haciéndolo más mantenible y más claro, sin necesidad de un artefacto externo que puede fácilmente quedar desactualizado. Antes de escribir cualquier documentación debemos preguntarnos varias cosas: ¿Es realmente imprescindible? ¿Será fácil de mantener? ¿Aporta algún valor claro para nuestro cliente? El manifiesto ágil resume lo aquí expuesto de la siguiente manera: “El software que funciona es más importante que la documentación exhaustiva”. El desarrollo de software va sobre código fuente y ejecutables, no sobre documentos. <<dotNetManía Solo el software que pueden ejecutar y utilizar es susceptible de crear valor para nuestros clientes. Solo el software que funciona debe ser la medida del progreso de los proyectos de desarrollo 11 entrevista Marino Posadas entrevista a Marino Posadas es director de tecnologías de desarrollo para España y Portugal de Solid Quality Learning. Puedes leer su blog en http://www. elavefenix.net. Catherine Heller Catherine Heller es española (nacida en Madrid) de padre norteamericano, y con muchos años de estancia en los dos países. En la actualidad, trabaja como evangelista de Windows Live, en Redmond, y anteriormente, de Visual Studio Tools for Office. Eso fue después de pasar en Microsoft Ibérica otra buena parte de su carrera… Cuéntanos tu trayectoria anterior en Microsoft Ibérica y –para los que ya te conocemos y te vimos marchar-, qué haces ahora en EE.UU. Yo empecé en Microsoft, en España, en el año 2000, como Aplication Development Consultant, y trabajaba con los ISV en España y les ayudaba a crear su planificación y arquitectura usando tecnologías de Microsoft. En el 2003 me salió la oportunidad de ir como Technical Evangelist a un grupo en Microsoft Corporation en Redmond. Mi primer TechEd aquí en Barcelona fue justo antes de trasladarme a Redmond. << dnm.directo.entrevista He seguido todo este tiempo como evangelista, pero cambiando entre productos. Me pasé dos años enfocada en Whidbey (concretamente en el área de Visual Studio Tools for Office), lo que fue muy interesante, porque anteriormente había sido especialista en servicios Web, en middle tier, en remoting, COM+… Especialmente sabiendo que vienes de un background de C++… Sí, había sido desarrolladora de C++ 10 años antes de venir a Microsoft… Fue muy interesante ver el desarrollo ¿qué resumen das a los lectores de la revista de cara a aprovechar ese potencial? En el TechEd de noviembre del año pasado di una charla sobre Windows Vista y las áreas en las que yo me centré, sobre todo Desktop Search. Hay una manera muy sencilla de poder incorporar búsquedas utilizando el índice del desktop, utilizando OLE DB Provider for Windows Search, y eso se utiliza muy fácilmente desde ADO.NET y está bien documentado. Es un proveedor algo especial, dado que es de solo lectura. mentar interfaces COM. Pero es factible, y también me dediqué a ayudar a los ISV en ese aspecto. También me centré en cosas como ayudar a los desarrolladores a conocer el impacto de User Account Control (UAC) sobre sus aplicaciones, porque es una pena ver cuántos lo deshabilitan cuando es un mecanismo muy importante para el usuario. Y realmente tampoco es tan complicado tener una aplicación que funcione bien con UAC. Es más bien conocer un poco el manifiesto que hay que embeber y resulta sencillo. desde el punto de vista del desarrollador de Office y la posibilidad de escribir código para Office desde .NET en C# y Visual Basic. Con Visual Studio 2005 en el mercado, me cambié a Windows Vista. En esa época todo el mundo hablaba de Indigo y Avalon, pero yo me puse a mirar las API nativas, que realmente es lo que venía como parte del sistema operativo. Fue un año y medio interesante, volviendo a mis orígenes de C++ y COM, pero también analizando cómo se podían aprovechar esas API nativas desde .NET, y los retos para acceder a ellas. Ya en enero, cuando lanzamos Windows Vista, me cambié a un mundo totalmente diferente, como es Windows Live. Respecto a ese año y medio de análisis de las API nativas de Vista, Pero hay toda una infraestructura para quienes quieran integrar sus datos dentro del índice, algo más complicada, ya que hablamos de tener que implementar interfaces COM desde C++. Pero el 99,9% de las veces lo que necesitas es leer, no escribir… Sí, leer es muy fácil. Cuando es más complicado y se requiere un nivel técnico mayor es, por ejemplo, cuando tenemos un formato de archivo propio y queremos indexar su contenido, o si queremos que el contenido del archivo o de ese tipo de archivos se integren en la experiencia visual del explorador. Por ejemplo, los Live Icons: ver la imagen allí, o poderla ver en la vista de presentación preliminar, o poder permitir que el usuario le asigne propiedades al archivo… todo esto requiere imple- Y de ahí pasaste a Windows Live y su parte programática… La primera cosa importante a entender sobre Windows Live es que es una oferta para el consumidor, no tanto para la empresa, salvo si ésta quiere integrarlo en sus portales Web dirigidos a usuarios finales. Gran parte de la oferta hoy sí va dirigida al usuario final. Estamos empezando a evolucionar hacia una plataforma, y tenemos una serie de ofertas para el desarrollador que, si bien no abarcan todavía el abanico de ofertas para el usuario final, son muy interesantes. Uno de los nuevos servicios que sacamos en versión alfa en abril se llama Silverlight Streaming by Windows Live. Es interesante porque es un servicio que hemos introducido <<dotNetManía Catherine Heller junto a Marino Posadas 13 <<dotNetManía << dnm.directo.entrevista 14 directamente a nivel de plataforma, no hay una oferta correspondiente para el usuario final. Se entiende que esto va dirigido al desarrollador. Es un servicio que complementa las aplicaciones Silverlight. Cuando vayamos creando aplicaciones Silverlight que sean muy ricas en elementos multimedia, que tengan vídeo, que tengan fotos, imágenes, esas aplicaciones podrán hacer uso del servicio de Silverlight Streaming. O sea, lo que es ahora la oferta de Silverlight 1.0, porque en la 1.1 cambian muchas cosas… Sí, pero esto vale tanto para Silverlight 1.0 como para 1.1, porque no afecta directamente esa API de programación sino que se crea un paquete, se incluyen todos los archivos de la aplicación, se crea un ZIP y se publica, o se sube ese paquete al servicio. Una vez allí, lo que se hace es proporcionar una experiencia de reproducción en una página Web, con la ventaja que esa aplicación se distribuye a lo largo de toda nuestra red de entrega de contenido (CDN, Content Delivery Network). Con esto, los elementos pesados están en el límite más cercano al usuario y no necesariamente en servidores centrales que pueden estar ubicados muy lejos. Además, tareas como el streaming de vídeo suelen requerir muchos recursos de hardware. Todo este trabajo duro lo hace el propio servicio. Y es una oferta muy interesante porque damos hasta 4Gb de espacio totalmente gratuito, y hasta que la versión definitiva del servicio salga a la luz (mientras estemos en alfa y beta), no hay ningún tipo de límite en el uso que se haga de él, es totalmente gratuito. Una vez que lo pongamos en producción pues sí se cobrará, pero solo a partir de un millón de minutos de streaming al mes. Tenemos el umbral muy alto, muy generoso… Para evitar excesos, simplemente, pero para que los usuarios “normales” puedan usarlo sin pagar… Bueno, esto refleja el objetivo que tenemos con los términos de uso en general para los servicios de Silver- light de plataforma. Queremos definir unos umbrales de uso muy generosos y permitir que por debajo de ese umbral el uso sea gratuito. Y en algún momento financiaremos eso a través de anuncios. Luego queremos también ofrecer un modelo para que por encima de ese umbral se pueda pagar, bien por usuario, o por transacción, o por minuto, dependiendo del servicio o por algún tipo de compartición de ingresos por anuncios; esa es la idea que tenemos detrás de estos servicios. También estamos haciendo una apuesta muy importante respecto a las fotografías almacenadas en Windows Live Spaces. Ahora mismo hay 4 mil millones de fotografías almacenadas. Baste pensar que los usuarios –de media– suben unos 8 millones de fotografías todos los días en todo el mundo. Vemos dónde se está haciendo un uso muy importante de Spaces: publicar y compartir fotografías. Lo bueno que tiene Spaces es que se puede crear un space y limitar a que solo tu familia, tus amigos o quien tú decidas acceda a él. Estamos invirtiendo mucho para hacer que Spaces sea un sitio idóneo para guardar fotografías, para crear experiencias de usuario como Windows Live Photo Gallery, que acabamos de sacar y que tiene una experiencia rica en el cliente para manipu- lar, personalizar tus fotos, etc. y desde allí subirlas directamente a tu space. Una vez en el space, el desarrollador puede integrar esas fotografías o experiencias que los usuarios ya han subido a su space, pues hay muchos tipos de experiencias que incorporan esas fotografías de manera muy interesante. Allí estamos potenciando maneras fáciles de acceso, como puede ser con un control Javascript que pongas en una página y permita al usuario seleccionar fotos o feeds RSS, o una API que permite subir fotos, borrarlas, etc. Queremos extender la experiencia de esas fotografías a otros sitios Web, a otras aplicaciones. Bueno, para finalizar, para el que quiera programar alguna cosa con Windows Live ¿cuáles serían los primeros pasos a dar? Lo primero, desde luego, es ir al sitio Web, que es http://dev.live.com. Ese es el sitio para toda la información relacionada con el desarrollo utilizando los servicios de Windows Live. Allí se enlaza a la documentación MSDN y se ofrecen aplicaciones (las Quick Applications) que demuestran cómo combinar varios servicios. En CodePlex está el código fuente disponible y se puede participar en esa comunidad para extender esas aplicaciones, y hay muchas más ofertas para desarrolladores. Cuando tomamos decisiones, necesitamos información; esa información nos ayuda a gestionar mejor los procesos de nuestras organizaciones y a ser más competitivos, dándonos mejores posibilidades de supervivencia en el corto, medio y largo plazo. Aproximadamente el noventa por ciento de la información que necesitamos está dentro de nuestra propia organización, pero por desgracia la dispersión de la información (múltiples fuentes de datos, múltiples formatos, calidad del dato mostrado, etc.) hace que solo el treinta por ciento esté accesible en el formato y en el tiempo adecuado; el resto son datos por tratar o información no estructurada... si no lo tienes claro... GR d La revista de la Gestión del Rendimiento La revista para la Gestión del Rendimiento www.gestiondelrendimiento.com eventos Marino Posadas TechEd 2007: expectación ante un año pleno de novedades << Quien más quien menos tenía la idea de que la recién concluida edición del TechEd 2007 en Barcelona iba a ser la antesala de las innovaciones que se esperan para el 2008: Windows Server 2008, Visual Studio 2008 (cuya disponibilidad final se anunció durante el evento), SQL Server 2008, Silverlight, etc. Y así fue. Tuvimos ocasión de asistir a excelentes sesiones (las hubo de todas clases), abrir los ojos a nuevas tecnologías y como siempre, compartir con una comunidad cada vez más activa. mantener, como clave del éxito de la compañía. A partir de ahí, la marabunta… ¡hasta 15 sesiones simultáneas! Siendo grande el foro que alojó el evento, se tuvieron que habilitar dos zonas exteriores cubiertas para dar cabida a la gran cantidad de ponentes que se dieron cita este año. Y además de las sesiones estándar, estaban las interactivas (en las que el usuario puede interrumpir al ponente con sus preguntas desde el principio), que en esta edición tuvieron más éxi- Somasegar, durante la keynote Marino Posadas es director de tecnologías de desarrollo para España y Portugal de Solid Quality Learning. Puedes leer su blog en http://www. elavefenix.net. Fue Soma Somasegar (vicepresidente corporativo de la División de Desarrollo) el encargado este año de abrir las sesiones con una keynote en la que fue introduciendo la mayor parte de las novedades que se espera vayan apareciendo desde ahora hasta finales de 2008 (o hasta el siguiente TechEd, que repetirá ubicación en Barcelona). Ayudado por Tony Goodhew y Dan Fernandez en las presentaciones, fue desglosando uno a uno los elementos clave de cada producto y presentando un ecosistema cada vez más integrado, más colaborador con su entorno, más fácil de usar: el mantra habitual que oímos en muchas presentaciones y que Gates trata por todos los medios de to que nunca. Se presenta un tema (normalmente el mismo que el ponente ha expuesto en una sesión estándar), y se debate en profundidad discutiendo y aportando cada espectador sus miedos o experiencias en la implementación. En la foto adjunta, vemos a Francisco González de Solid Quality Mentors, único ponente español junto a Catherine Heller, atender al público al final de su sesión interactiva. Afortunadamente, los asistentes al evento recibiremos un “post-conference DVD” con todo el contenido de las ponencias grabado en vídeo junto a las presentaciones PowerPoint y código fuente. Por suerte, otra novedad de este TechEd con- << dnm.directo.eventos Francisco González, único ponente de una compañía española (Solid Quality Mentors) sistió en que desde la semana posterior al evento no tenemos que esperar la llegada del DVD para ver las sesiones que nos perdimos, ya que pueden verse online desde la página Web de TechEd Europa (http://www.mseventseurope.com/TechEd/Developers). Pero había muchas otras formas de colaboración: la sección Ask The Experts contaba con mucha más presencia (el público votó masivamente a favor de esta iniciativa), se habilitaron –como siempre– zonas wireless (Delegate Work Area y Communications Network) donde el personal podía atender sus urgencias corporativas, y la zona de Exhibitors estaba como siempre, llena de curiosos por ver las ofertas de compañías de terceros, que este año contaban incluso con una tienda de ropa con distintos logos de productos Microsoft. ¿Falta uno? Sí. Falta mencionar la que fue –quizás– mi entrevista favorita de este año, con Don Syme, de Microsoft Research (Cambridge), arquitecto principal del lenguaje funcional F#, que se incorpora de pleno derecho a la familia de lenguajes soportados por Visual Studio en la siguiente versión, y que ofrece unas características para el cálculo matemático como no habíamos visto hasta ahora. Don es un tipo muy accesible, y nos estuvo enseñando in situ, con su propio portátil, algunas de las carac- Don Syme nos explica -en su demo de F#– la potencia del lenguaje en cálculo matricial tecto de SQL Server 2000/2005, que dio un auténtico espectáculo en sus presentaciones sobre filosofía del software), o Jesse Liberty, quien, recientemente fichado por la compañía, se ha convertido en el alma evangelizadora de Silverlight en Redmond. También estuvimos con otros evangelistas, como la española (de padre norteamericano) Catherine Heller, que dedica sus esfuerzos actuales a la divulgación de Windows Live, Joe Marini, Program Manager del equipo de extensibilidad de Visual Studio, Dan Fernandez, Lead Product Manager de herramientas como PopFly o Visual Studio Express y jefe de Arturo Toledo, otro de nuestros entrevistados (ver dotNetManía nº 40) y Damir Tomicic, Presidente de INETA Group Europe. terísticas más sobresalientes de este nuevo miembro de la familia .NET. Iremos publicando estas entrevistas en los próximos números de la revista. También hubo lugar para el esparcimiento, tanto en la zona XBox como después de las jornadas, con cenas para la comunidad MVP española, dirigida por Cristina González Herrero, para las comunidades nacionales por países, y para certificados Microsoft, donde hizo de anfitriona Karen Young, EMEA MVP Regional Manager. Un TechEd, en suma, más intimista (sin la super-fiesta final del jueves), más centrado en el trabajo, con un altísimo nivel de sesiones, y donde pudimos contactar más directamente que nunca con aquellos que están haciendo y presentando el software que todos queremos utilizar en el inmediato futuro. <<dotNetManía Hall principal de expositores y zonas comunes Hubo muchos conferenciantes distinguidos, pero lo mejor es que tuvimos oportunidad de entrevistar a 8 de ellos para dotNetManía. Hablamos con auténticos clásicos de la tecnología Microsoft, como Ted Pattison (Presidente de Ted Pattison Group y conocido autor del mundo COM), Pat Helland (coautor de MTS y arqui- 17 << dnm.directo.eventos <<dotNetManía Lanzamiento de Biztalk 18 La verdad es que desde el principio la cosa prometía. Pónganse en situación: Museo Thyssen de Madrid, un evento de todo un día dedicado exclusivamente a Biztalk, un montón de buenas referencias de implantaciones Biztalk verticalizadas en 3 grupos (banca y seguros, industria y sector público), charlas técnicas focalizadas en las novedades de esta revisión de Biztalk, raona como Partner Platinum presentando un caso de éxito implantado en Catalana Occidente y una difusión del evento a la base de datos de Microsoft, formada por unos 6000 contactos. La primera de las ponencias que figuraban en la agenda tras la bienvenida a los asistentes por parte de Fernando Bocigas, responsable del producto en España, corría a cargo de Fernando García, director de Ventas de Soluciones de Aplicación en Microsoft, que bajo el título “Seis tendencias tecnológicas que marcarán la próxima década” contextualizó de manera general el estado actual de la tecnología, y auguró los principales retos a los que tendremos que hacer frente en un futuro inmediato como responsables de IT y como usuarios que conviven en el día a día con la información. La verdad es que aquí, como en otros ámbitos, Microsoft marca tendencias, así que no es arriesgado aventurar que darán en el clavo y que, efectivamente, la evolución lógica que se nos presentó (¿les suena “mundo interconectado”?) será acertada. Tras Fernando García, de nuevo fue el turno de Fernando Bocigas, con una ponencia llamada “Extendiendo el negocio conectado”, en la que se hizo un repaso de cuál ha sido la evolución del producto desde sus orígenes (cómo han cam- 2006 R2 biado las cosas, afortunadamente, desde aquel Biztalk 2000 “intratable”) hasta la actual versión 2006 R2. Sorprende ver cómo progresivamente se va ganando la aceptación de las compañías, pasando de 500 clientes en la primera versión hasta aproximadamente 7000 con la, hasta la fecha, última versión con datos fiables, Biztalk 2006. En este caso, Microsoft fue prudente y se reservó el dar una fecha estimada de la previsión de calado de R2 para cuando alcance la etapa de madurez, aunque nada hace indicar que la tendencia al alza se frene. Biztalk como integrador de una cadena de fabricación de componentes para el interior del automóvil; una implantación en un centro de salud para la comunicación de diferentes áreas y departamentos; un caso real de utilización del adaptador SWIFT para transacciones seguras dentro del entorno de banca… El caso de éxito por el que raona fue invitado al evento consistía en la comunicación de la compañía de seguros Catalana Occidente con el Ministerio de Justicia con la finalidad de hacerle llegar datos Las exposiciones no defraudaron y nos mostraron Biztalk como una realidad que funciona y que goza de un merecido respeto en las compañías en las que ha sido implantado Y, por fin, el plato fuerte del día: casos de éxito de implantaciones reales de Biztalk 2006. Los hubo para cada una de las verticales que, por parte de Microsoft, acudían al evento: industria, sector público y bancaseguros. Por este orden, los diferentes partners que acudieron al evento fueron exponiendo sus desarrollos, presentando 2 casos de éxito para cada vertical. Pudimos ver un sinfín de problemáticas diferentes con un denominador común: Biztalk. Entre los casos destacados se mostraron un requeridos de las pólizas de vida, en virtud de la ley 20/2005 sobre la creación del Registro de Contratos de Seguros de Cobertura de Fallecimiento. La verdad es que las exposiciones no defraudaron y nos mostraron Biztalk como una realidad que funciona y que goza de un merecido respeto en las compañías en las que ha sido implantado. Déjenme hacerles una confesión: en los numerosos años que llevo haciendo implantaciones de Biztalk, jamás me he encontrado con un << dnm.directo.eventos cliente que se haya sentido defraudado por el resultado final, ni en cuanto a expectativas de rendimiento ni en cuanto a capacidad de integración. Llegó el momento de recobrar fuerzas con el cóctel programado para afrontar la recta final del evento con las energías renovadas. Respecto a lo acontecido por la tarde, poco tenemos que comentar: tres diferentes charlas, eminentemente técnicas, en las que sin grandes pretensiones se nos detalló el funcionamiento de los adaptadores RFID y EDI mejorados para esta última versión, y una última charla que cerraba el día y que rezaba algo así como “Extendiendo SOA desde la Empresa al Mundo” (previsible, muy previsible…). Y esto fue todo. Al final, menos asistencia de la prevista: 75 participantes entre partners, clientes e invitados. Una impecable organización, en la que los tiempos se cumplieron rigurosamente, y un buen sabor de boca respecto a los incrementales esfuerzos por parte de Microsoft por situar Biztalk en el lugar que le corresponde como herramienta de integración de primer nivel. Suriel Hilario Project Manager de Raona CEUS 2007 El pasado 30 de octubre, cerca de 320 personas asistieron a la tercera edición de CEUS 2007, la III Conferencia de Usuarios de SharePoint, en Madrid. Esta edición sirve para consolidar dichas conferencias entre la comunidad y confirma el éxito de la plataforma de moda de Microsoft. Prueba de ello fue el número de asistentes, que superó al del año pasado, confirmando el interés de la plataforma SharePoint. El día se dividió en dos formatos totalmente diferentes de presentaciones. La mañana estuvo presidida por presentaciones de empresas usuarias de SharePoint, que junto al cliente final, nos mostraron casos de éxito con SharePoint; en la presentación daban a conocer a todo el aforo su experiencia, implementación y sensaciones con el producto. Entre estas empresas se encontraban raona junto a su cliente Criteria Caixa Corp, Getronics con Ancert y K2, Renacimiento con el Ministerio de Presidencia e Informática el Corte Inglés con Caja Mediterráneo. Todas estas presentaciones fueron de carácter práctico, con la puesta en marcha del proyecto y las peculiaridades de cada uno. Enmedio, y después del descanso, intervinieron distintos responsables de Microsoft, que nos dieron algunos detalles del futuro de SharePoint, enfocado en las búsquedas, lo que anuncia la salida del nuevo SharePoint Search Server. Por parte de Microsoft, contamos con la presencia de Rafael Sánchez, jefe de producto de SharePoint, y con Sarah Hammon, responsable de producto SharePoint en Europa. Las sesiones de la tarde, en cambio, fueron sesiones mucho más técnicas, más enfocadas hacia un tema específico. Se contó con un total de siete salas, y en cada una de ellas tuvieron lugar tres presentaciones de unos 55 minutos cada una. Con este formato de presentaciones y con la disponibilidad de salas, los asistentes se dividieron entre las sesiones más interesantes para cada uno de ellos. Se trataton temas muy diversos, desde migraciones de SharePoint 2003 y CMS 2001 a SharePoint 2007, hasta integraciones de BI, Microsoft Dynamics, Business Data Catalog, workflows con SharePoint Designer y definición de arquitecturas de alta disponibilidad. Los ponentes de estas presentaciones pertenecían a las distintas empresas patrocinadoras del evento y otros voluntarios, así como personal de Microsoft. Todas las presentaciones estarán disponibles públicamente en breve para las personas que no puedieron asistir al evento. Entre las novedades, la nueva versión de Microsoft Search Server 2008. Esta versión del nuevo buscador para SharePoint ya se encuentra liberada en su versión release candidate para que cualquiera de los usuarios pueda descargarla y probarla. Sergio Holgado Software Engineer de Raona plataforma.net Javier Roldán Tablet PC SDK (y II) Reconocimiento de escritura manual En la primera parte de este artículo indicamos el modo de preparar el entorno de desarrollo necesario para la programación de aplicaciones capaces de aceptar tinta digital para más tarde reconocerla como escritura manuscrita.Asimismo, utilizamos los principales elementos que para este fin proporciona el Microsoft Windows XP Tablet PC Edition Software Development Kit. Fco. Javier Roldán Huecas es ingeniero superior informático. Con una experiencia laboral de ocho años como profesional del sector de las TI, en la actualidad trabaja como ingeniero de sistemas y responsable de proyectos en una importante empresa industrial de ámbito nacional. [email protected] Estos elementos, flexibles y de sencilla incorporación a nuestros proyectos, eran el control InkEdit y el control InkPicture. El primero permitía la captura de trazos de tinta digital y su reconocimiento de manera automática, todo ello sin escribir una sola línea de código. Por otro lado, el control InkPicture permitía la captura automática de trazos de tinta digital; sin embargo, para el reconocimiento de los trazos como escritura era necesario un poco de programación. En el presente artículo iremos más allá y estudiaremos la manera de hacer que cualquier control (como por ejemplo un Panel, un RichTextBox o un ListBox, por solo poner unos ejemplos) sea capaz de aceptar trazos de tinta digital y reconocerlos como escritura manual. Asimismo, veremos los principales métodos existentes para mejorar la efectividad del reconocimiento, tales como el uso de los factoids (cadenas predefinidas que proporcionan al reconocedor información sobre el tipo de texto a reconocer) y wordlists (listas predefinidas de palabras). Para finalizar, analizaremos el uso de lo que se conoce como gestures, gestos especiales no reconocidos como palabras y que permiten la ejecución de acciones a medida. damos. Al igual que el control InkPicture, la clase InkOverlay no proporciona por defecto métodos automáticos para el reconocimiento de la escritura manual; sin embargo, del mismo modo podremos suplir esta ausencia mediante la clase Recognizers y un poco de programación. Pasemos por tanto a ver cómo usar la clase InkOverlay. Para ello, crearemos un nuevo formulario a imagen y semejanza del formulario usado en la primera parte de este artículo, con la diferencia de que sustituiremos el control InkPicture por un simple Panel. Para aquellos que no hayan podido leer esa primera parte, el formulario se compone básicamente de un control Panel sobre el que escribiremos trazos de tinta digital, un TextBox en el que mostraremos el resultado de inten- La clase InkOverlay La clase InkOverlay nos permite añadir características de tinta digital a cualquier control que deci- Figura 1. Formulario InkOverlay. << dnm.plataforma.net this.inkOverlay = new InkOverlay(this.panelEscritura); this.inkOverlay.Enabled = true; Como podemos observar, en la primera línea de código simplemente creamos una instancia de la clase InkOverlay, a la que le pasamos en el constructor el control con el que queremos asociarlo. En la segunda línea activamos dicha instancia. Si ejecutamos la aplicación de nuevo, observaremos que hemos convertido el Panel en un control capaz de recibir trazos de tinta digital; pero que (al igual que ocurría con el control InkPicture) éste no es capaz de reconocerlos como texto de manera automática. Utilizando el mismo código que el usado en el artículo anterior para el control InkPicture, pero sustituyendo la referencia a la clase InkPicture por la clase InkOverlay, haremos posible que el texto manuscrito sobre el control Panel sea reconocido y mos- trado en el cuadro de texto. Del mismo modo, podremos borrar, seleccionar, escalar y mover cada trazo dibujado con solo using using using using using using using using añadir el código necesario a los botones de la interfaz de usuario. Puede verse el código completo en el listado 1. System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Text; System.Windows.Forms; Microsoft.Ink; namespace InkOverlayTest { public partial class FormInkOverlay : Form { private InkOverlay inkOverlay; public FormInkOverlay() { InitializeComponent(); } private void FormInkOverlay_Load(object sender, EventArgs e) { this.inkOverlay = new InkOverlay(this.panelEscritura); this.inkOverlay.Enabled = true; } private void buttonEscribir_Click(object sender, EventArgs e) { this.inkOverlay.EditingMode = InkOverlayEditingMode.Ink; } private void buttonBorrarTrazo_Click(object sender, EventArgs e) { this.inkOverlay.EraserMode = InkOverlayEraserMode.StrokeErase; this.inkOverlay.EditingMode = InkOverlayEditingMode.Delete; } private void buttonBorrarPunto_Click(object sender, EventArgs e) { this.inkOverlay.EraserMode = InkOverlayEraserMode.PointErase; this.inkOverlay.EditingMode = InkOverlayEditingMode.Delete; } private void buttonSeleccionar_Click(object sender, EventArgs e) { this.inkOverlay.EditingMode = InkOverlayEditingMode.Select; } private void buttonReconocimiento_Click(object sender, EventArgs e) { Recognizers reconocedores = new Recognizers(); if (reconocedores.Count != 0) { Recognizer reconocedor = reconocedores.GetDefaultRecognizer(); RecognizerContext contextoReconocedor = reconocedor.CreateRecognizerContext(); <<dotNetManía tar reconocer los trazos como texto y una serie de cuatro botones que nos permitirán escribir trazos, modificarlos y borrarlos. Por último, dispondremos de un botón que lanzará el evento de reconocimiento de escritura. Puede verse como queda dicho formulario en la figura 1. Si ejecutamos la aplicación e intentamos realizar algunos trazos sobre el Panel, veremos que (como era de esperar) nada sucede. Esto es debido a que el control Panel, al contrario de lo que ocurría con el control InkEdit o InkPicture, no espera que sobre él se dibujen trazos de tinta digital, por lo que detecta los eventos del ratón (o puntero) como simples eventos de pulsación y arrastre. La solución pasa por “superponer” sobre el control Panel (o cualquier otro sobre el que queramos escribir) un control que es capaz de capturar y mostrar trazos de tinta digital. Dicho control se implementa a través de la clase InkOverlay. Para ello, añadimos el siguiente código al evento Load del formulario: 21 << dnm.plataforma.net RecognitionResult resultadoReconocedor; RecognitionStatus estatusReconocimiento; contextoReconocedor.Strokes = inkOverlay.Ink.Strokes; if (contextoReconocedor.Strokes.Count > 0) { resultadoReconocedor = contextoReconocedor.Recognize(out estatusReconocimiento); if (estatusReconocimiento == RecognitionStatus.NoError && resultadoReconocedor != null) { String resultado = resultadoReconocedor.TopString; if (resultado != null && resultado.Length > 0) { this.textBoxTextoReconocido.Text = resultado; } } } } else { MessageBox.Show(“No existen reconocedores instalados”); } } Figura 2. Reconocimiento sin factoids. to_Click, justo tras la línea donde creamos el RecognizerContext: contextoReconocedor.Factoid = Factoid.Number; O bien esta otra línea, totalmente equivalente a la anterior: } contextoReconocedor.Factoid = “NUMBER”; } <<dotNetManía Listado 1. Código de reconocimiento de escritura con InkOverlay. 22 Mejorando el reconocimiento varias herramientas, entre las que se encuentran los factoids y las wordlists. A estas alturas, si ha seguido de manera práctica el artículo, con total seguridad ya habrá probado la sorprendente eficacia del reconocedor implementado en el Microsoft Windows XP Tablet PC Edition 2005 Recognizer Pack. Sin embargo, existen situaciones en las que es muy difícil para cualquier reconocedor automático de texto averiguar qué es lo que el usuario exactamente ha querido escribir. Pensemos, por solo poner un par de ejemplos, en aquellos casos en los que es necesario que la aplicación reconozca letras sueltas, o palabras sin ningún sentido en cualquier idioma, como nombres de usuario o contraseñas. Para poder enfrentarnos con éxito a este tipo de casuísticas, el Microsoft Windows XP Tablet PC Edition Software Development Kit pone a nuestra disposición Factoids Si ahora ejecutamos la aplicación y escribimos de nuevo el número 51, nos lo reconocerá sin problemas. Sin embargo, si probamos a escribir el carácter ‘1’ de un tamaño considerablemente mayor que el ‘5’, es posible que el reconocedor nos interprete el texto como la cadena “s1” (figura 3). Los factoids son constantes de tipo string que asignadas a la propiedad Factoid de la clase RecognizerContext que proporcionan información contextual al reconocedor que permite mejorar la efectividad de reconocimiento. Para entenderlo mejor, veamos un sencillo ejemplo. Supongamos que en la aplicación de ejemplo del apartado anterior quisiéramos reconocer únicamente cifras numéricas introducidas por el usuario. Pues bien, si ejecutamos la aplicación e intentamos escribir el número 51 pero de un modo un tanto simplificado, el reconocedor lo interpretará como la cadena de texto “si” (ver figura 2). Para solucionar este contratiempo, añadimos la siguiente línea de código dentro del evento buttonReconocimien- Figura 3. Reconocimiento usando factoids. Hemos mejorado el reconocimiento, sin embargo no hemos alcanzado el << dnm.plataforma.net objetivo de que la aplicación reconozca todo el texto introducido por el usuario exclusivamente como números. Para forzar al reconocedor a que interprete los trazos introducidos únicamente dentro del contexto especificado por la propiedad Factoid, debemos incorporar la siguiente línea de código a nuestra aplicación: contextoReconocedor.RecognitionFlags= RecognitionModes.Coerce; minar el formato de cada factoid en función del idioma que estemos utilizando. Asimismo, debemos tener en cuenta que no todos los factoids existen en todos los idiomas, por lo que es recomendable tener muy claro en qué idioma estamos trabajando y usar los factoids que correspondan. En la tabla 1 se presentan los principales factoids, divididos en dos grandes grupos: dependientes e independientes de idioma. No se han incluido, por encontrase fuera del alcance de este artículo, los factoids de idiomas orientales (japonés, chino y coreano). Wordlists Existen situaciones en las que el uso de factoids es del todo inadecuado, y sin embargo el reconocimiento por defecto sigue siendo deficiente. Pensemos por ejemplo aquellos casos en los que la aplicación deba reconocer palabras sin sentido que combinen letras y números, como por ejemplo nombres de usuario y contraseñas. Si volvemos al ejemplo inicial e intentamos reconocer por ejemplo la cadena “ ss5lo10”, pero además no haciendo distinción alguna mientras Factoids independientes de idioma Digit Dígito simple. Email Direcciones de correo electrónico. Web Diferentes tipos de URL. Los valores por defecto del reconocedor incluyen el factoid Web, por lo que no existe mayor diferencia entre usar este factoid y no usarlo. Default Devuelve al reconocedor a sus valores por defecto. En idiomas occidentales, esto incluye el diccionario de sistema, el diccionario de usuario, los signos de puntuación y los factoids Web y Number. En idiomas orientales, incluye todos los caracteres soportados por el reconocedor. None Desactiva todos los factoids y diccionarios. No debe usarse el modo Coerce con este factoid. Figura 4. Forzando el uso de factoids. Factoids dependientes de idioma Filename Rutas de fichero de Microsoft Windows. No incluye los caracteres / “ < > |. SystemDictionary Activa en exclusiva el diccionario de sistema. Wordlist Currency Activa en exclusive la lista de palabras. Cantidades monetarias en libras, euros, dólares y yenes, escritos en función del idioma. Fechas escritas en función del idioma. Todos los números, incluyendo ordinales, símbolos matemáticos y unidades de medida (mm, kg,…), todos ellos en función del idioma. También están incluidos los factoids Date, Time, Telephone y Currency. Date Number OneChar Un carácter ANSI. Percent Un número seguido del símbolo %. Existirá un espacio entre el número y el símbolo de porcentaje en función del idioma. PostalCode Códigos postales en función del idioma. Telephone Números de teléfono en función del idioma. Time Horas y minutos escritos en función del idioma. UpperChar Una letra mayúscula. Tabla 1. Principales factoids <<dotNetManía Sin embargo, debemos usar con cuidado la combinación de la propiedad Factoid y el modo de reconocimiento Coerce, ya que tal y como hemos comentado, el modo Coerce fuerza a reconocer únicamente aquellas cadenas de texto que concuerden exactamente con la definición del factoid. Así por ejemplo, el factoid Email en modo Coerce solo reconocerá cuentas de correo electrónico completas; es decir, que contengan el carácter @ y un dominio totalmente cualificado (por ejemplo [email protected]), no permitiendo el reconocimiento de textos que no cumplan estrictamente estos requerimientos, como por ejemplo aliases (JavierRoldan) o cuentas de correo sin dominios totalmente cualificados, comunes en algunas implementaciones de mensajería interna (javier.roldan@midominio). Es importante señalar que mientras algunos factoids, como por ejemplo Email y Web, son idénticos en cualquier idioma, otros, como por ejemplo Telephone y PostalCode dependen del idioma utilizado. Es fundamental por tanto exa- 23 << dnm.plataforma.net Gestures escribimos entre el ‘5’ y la ‘s’, el ‘1’ y la ‘l’ y el ‘0’ y la ‘o’, parece imposible que ninguna aplicación (o incluso persona) pueda reconocer ese texto (figura 5). Figura 6. Reconocimiento mediante wordlists Figura 5. ¿Reconocimiento imposible? Sin embargo, existe un modo de hacer que este reconocimiento funcione, y es proporcionando al reconocedor una lista de palabras posibles a introducir por el usuario. Es lo que se conoce como el uso de wordlists. Añadiremos el siguiente código dentro del evento buttonReconocimiento_Click, justo tras la línea donde creamos el RecognizerContext y en sustitución del código añadido en el apartado anterior (ver listado 2): private void buttonReconocimiento_Click(object sender, EventArgs e) { Recognizers reconocedores = new Recognizers(); if (reconocedores.Count != 0) { Recognizer reconocedor = reconocedores.GetDefaultRecognizer(); RecognizerContext contextoReconocedor = reconocedor.CreateRecognizerContext(); contextoReconocedor.Factoid = Factoid.WordList; WordList wordList = new WordList(); wordList.Add(“ss5lo10”); contextoReconocedor.WordList = wordList; contextoReconocedor.RecognitionFlags = RecognitionModes.Coerce; RecognitionResult resultadoReconocedor; RecognitionStatus estatusReconocimiento; contextoReconocedor.Strokes = inkOverlay.Ink.Strokes; <<dotNetManía contextoReconocedor.Factoid = Factoid.WordList; WordList wordList = new WordList(); wordList.Add(“ss5lo10”); contextoReconocedor.WordList = wordList; contextoReconocedor.RecognitionFlags= RecognitionModes.Coerce; 24 Podremos comprobar que la aplicación es capaz de reconocer los trazos introducidos sin mayor problema (figura 6). Teniendo en cuenta que es posible añadir en tiempo de ejecución tantas palabras como deseemos a la propiedad WordList, esto convierte su utilización en prácticamente obligada en todos aquellos casos en los que sea factible su uso. Finalizaremos el artículo haciendo un breve recorrido por el uso de los gestures. Los gestures son gestos o trazos especiales que no son reconocidos como palabras y que permiten la ejecución de acciones a medida. El Microsoft Gesture Recognizer soporta dos tipos de gestures: de sistema (SystemGesture) y de aplicación (ApplicationGesture). Los SystemGesture son gestos definidos y soportados por defecto y que en su mayoría son mapeados a eventos de ratón; como por ejemplo el gesto Tap, que es if (contextoReconocedor.Strokes.Count > 0) { resultadoReconocedor = contextoReconocedor.Recognize(out estatusReconocimiento); if (estatusReconocimiento == RecognitionStatus.NoError && resultadoReconocedor != null) { String resultado = resultadoReconocedor.TopString; if (resultado != null && resultado.Length > 0) { this.textBoxTextoReconocido.Text = resultado; } } } } else { MessageBox.Show(“No existen reconocedores instalados”); } } Listado 2. Usando wordlists para el reconocimiento de palabras complejas. << dnm.plataforma.net Digit Dígito simple. Tap Clic de ratón. DoubleTap Doble clic de ratón. RightTap Clic con el botón derecho del ratón. Drag Arrastre con el botón izquierdo del ratón. RightDrag Arrastre con el botón derecho del ratón. Se consigue haciendo un tap largo y luego arrastrando sin levantar el puntero de la pantalla. HoldEnter Sin equivalente en el ratón. HoldLeave No implementado. HoverEnter Equivalente a pasar el ratón por encima. HoverLeave Equivalente a dejar de pasar el ratón por encima. Tabla 2. SystemGesture disponibles mapeado a un clic de ratón. La lista de SystemGesture disponibles y su mapeo a eventos de ratón se presenta en la tabla 2. Por otra parte, los ApplicationGesture son gestos que podemos incluir (o no) libremente en nuestra aplicación. Para implementar este tipo de gestures, debemos añadir el siguiente código al evento Load del formulario: A continuación, el código establece qué tipo de gestures deseamos que sean reconocidos mediante el uso del método SetGestureStatus de la clase InkOverlay. En el ejemplo activamos el reconocimiento de todos los gestures. Es posible activar el reconocimiento de solamente ciertos gestures; para ello, sustituiríamos la línea de código anterior por una o más líneas equivalentes a las que vemos a continuación: Los gestures son gestos o trazos especiales que no son reconocidos como palabras y que permiten la ejecución de acciones a medida this.inkOverlay = new InkOverlay(this.panelEscritura); this.inkOverlay.CollectionMode = CollectionMode.InkAndGesture; this.inkOverlay.SetGestureStatus(ApplicationGesture.ChevronDown, true); this.inkOverlay.SetGestureStatus(ApplicationGesture.ChevronUp, true); this.inkOverlay.SetGestureStatus(ApplicationGesture.Check, true); this.inkOverlay.SetGestureStatus( ApplicationGesture.AllGestures, true); this.inkOverlay.Enabled = true; Como puede observarse en el código, inicialmente creamos un InkOverlay asociado al panel sobre el que deseamos escribir, para luego establecer su propiedad CollectionMode al valor CollectionMode.InkAndGesture. Esto nos permite indicar que tanto los trazos de tinta como los gestos deben ser reconocidos como tal. Por último, asociamos el método inkOverlay_Gesture al evento Gesture del objeto inkOverlay y lo activamos. El método inkOverlay_Gesture, que sim- plemente muestra en el cuadro de texto el texto asociado al gesture reconocido, se muestra a continuación: Podemos ver el código completo en el listado 3. No se ha incluido el código asociado a los botones de edición de trazos ni de reconocimiento de escritura, ya que éste se muestra íntegramente en el listado 1. void inkOverlay_Gesture(object sender, InkCollectorGestureEventArgs e) { this.textBoxTextoReconocido.Text = e.Gestures[0].Id.ToString(); } <<dotNetManía this.inkOverlay.Gesture += new InkCollectorGestureEventHandler( inkOverlay_Gesture); 25 << dnm.plataforma.net using using using using using using using using System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Text; System.Windows.Forms; Microsoft.Ink; namespace InkGestureTest { public partial class FormGestures : Form { private InkOverlay inkOverlay; public FormGestures() { InitializeComponent(); } private void FormGestures_Load(object sender, EventArgs e) { this.inkOverlay = new InkOverlay(this.panelEscritura); this.inkOverlay.CollectionMode = CollectionMode.InkAndGesture; this.inkOverlay.SetGestureStatus(ApplicationGesture.AllGestures, true); this.inkOverlay.Gesture += new InkCollectorGestureEventHandler(inkOverlay_Gesture); this.inkOverlay.Enabled = true; } void inkOverlay_Gesture(object sender, InkCollectorGestureEventArgs e) { this.textBoxTextoReconocido.Text = e.Gestures[0].Id.ToString(); } } } Listado 3. Implementación de los gestures. Si ejecutamos la aplicación y probamos a trazar gestos reconocidos como ApplicationGesture, veremos cómo de manera inmediata el texto asociado al gesture será mostrado en el cuadro de texto habilitado al efecto. <<dotNetManía Conclusión 26 Figura 7. Gesture DoubleCurlicue. Con esta segunda parte damos conclusión a nuestro artículo relacionado con el desarrollo de aplicaciones capaces de aceptar tinta digital y de reconocer la escritura manuscrita, que esperamos haya resultado útil e informativo para los lectores. plataforma.net Luis Miguel Blanco El evento CellPainting del control DataGridView Vía libre a la creatividad Cuando presentamos a nuestros usuarios un conjunto de datos mediante el control DataGridView, podemos mejorar la apariencia visual del mismo recurriendo al uso de estilos. No obstante, la mera utilización de estilos resulta escasa si nuestras pretensiones pasan por lograr efectos avanzados y un mayor control sobre el proceso de dibujo de las celdas. Es por ello que el empleo combinado del evento CellPainting, perteneciente a este control, junto al conjunto de clases de GDI+ (la API de programación gráfica de .NET Framework), se va a convertir en un poderoso recurso a nuestro alcance, que nos permitirá aplicar ese “toque especial” al dibujo de las celdas, para que luzcan con todo su esplendor. Porque ellas lo valen. CellPainting. Control total del dibujo de celdas Luis Miguel Blanco es redactor de dotNetManía. Es consultor en Alhambra-Eidos.Ha escrito varios libros y decenas de artículos sobre la plataforma .NET (lalibreriadigital.com) propiedades encontraremos también aquellas que nos permitirán realizar todo el dibujo de la celda y su contenido al completo. La tabla 1 muestra las propiedades más destacables de esta clase. Se trata de un evento que se produce para cada celda que va a dibujarse, con la particularidad de que el desarrollador Propiedad Descripción dispone de pleno Índice de la colección de columnas del control, que indica la columcontrol sobre toda la ColumnIndex na sobre la que se produce el evento. operación de dibujo de la celda, siendo RowIndex Índice de la colección de filas del control, que indica la fila sobre la posible aplicarle efecque se produce el evento. tos gráficos tales como CellBounds Objeto Rectangle con la posición y dimensiones de la celda a pintar. degradados (fundidos) Estado de la celda: seleccionada, visible, solo lectura, etc. de colores, texturas, State imágenes, etc. Graphics Objeto Graphics conteniendo el contexto de dispositivo gráfico sobre CellPainting reciel que realizar la operación de dibujo. be como parámetro Valor para pintar en la celda. un objeto DataGrid Value ViewCellPainting EventArgs , que nos servirá para obtener la información principal sobre la columna, fila y valor de celda. Además, entre sus FormattedValue Valor formateado para pintar en la celda. CellStyle Estilo de la celda. Handled Propiedad booleana que permite informar al control si la operación de dibujo ha sido realizada manualmente mediante el código suministrado por el programador, o deberá ser el control quien realice este proceso. Tabla 1. Propiedades de la clase DataGridViewCellPaintingEventArgs <<dotNetManía << dnm.plataforma.net 28 Es momento, por lo tanto, de ponernos manos a la obra y crear un nuevo formulario, al que añadiremos un DataGridView que nos sirva para experimentar con esta característica. Como es habitual, todos los ejemplos de este artículo se encuentran disponibles en el sitio Web de la revista. En este ejemplo aplicaremos la operación de dibujo manual a los campos ListPrice y Color, pertenecientes a la consulta SQL que mostraremos en el control de cuadrícula. Como paso previo, en el evento Load del formulario, después de asignar el DataSet con los datos al DataGridView, crearemos para los mencionados campos sendos estilos con un tipo de letra que destaque notablemente del resto de columnas, lo que vemos en el listado 1, donde adicionalmente se configura el ajuste de tamaño automático para filas y columnas, de modo que el contenido de estos campos se muestre correctamente. A continuación pasamos a escribir el código de CellPainting, donde nuestro objetivo consistirá en pintar las mencionadas celdas, dotándolas de un efecto de fundido de colores que conseguiremos gracias al uso de un objeto de la clase PathGradientBrush, que se encuentra ubicada en el espacio de nombres System.Drawing.Drawing2D. Un objeto PathGradientBrush, brevemente descrito, rellena una porción de la superficie del formulario tomando como base a una figura (por ejemplo, el rectángulo correspondiente a una celda del control), y le aplica un color central que será rodeado por otro conjunto de colores situados en un array. La forma en que los colores se distribuirán y fundirán al aplicar este objeto se determina gracias a un array de coordenadas (objetos Point), que en este caso estará compuesto por los mismos puntos de coordenadas que el rectángulo de la celda a pintar. Entre los diversos estados que puede tomar una celda se encuentran los correspondientes a normal y seleccionado. El estado actual de una celda se // obtención de datos SqlConnection cnConexion = new SqlConnection(); cnConexion.ConnectionString = “Data Source=localhost;” + “Initial Catalog=AdventureWorksDW;” + “Integrated Security=True”; //.... string sSQL; sSQL = “SELECT ProductKey, SpanishProductName, ListPrice, EndDate, Color “; sSQL += “FROM DimProduct “; sSQL += “WHERE ListPrice IS NOT NULL”; SqlCommand cmdComando = new SqlCommand(sSQL, cnConexion); SqlDataAdapter daAdaptador = new SqlDataAdapter(cmdComando); DataSet dsAdvWorks = new DataSet(); daAdaptador.Fill(dsAdvWorks, “DimProduct”); // establecer la fuente de datos para el DataGridView this.dgvGrid.DataSource = dsAdvWorks; this.dgvGrid.DataMember = “DimProduct”; // cambiar el tipo de letra a las columnas // que vamos a usar en el evento CellPainting DataGridViewCellStyle styListPrice = new DataGridViewCellStyle(); styListPrice.Font = new Font(“Comic Sans MS”, 16, FontStyle.Bold); styListPrice.Format = “C”; this.dgvGrid.Columns[“ListPrice”].DefaultCellStyle = styListPrice; DataGridViewCellStyle styColor = new DataGridViewCellStyle(); styColor.Font = new Font(“Papyrus”, 16, FontStyle.Bold); this.dgvGrid.Columns[“Color”].DefaultCellStyle = styColor; // establecer ajuste de altura automático para las filas this.dgvGrid.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells; // establecer ajuste de anchura automático para las columnas this.dgvGrid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells; // ocultar la primera columna del control this.dgvGrid.Columns[“ProductKey”].Visible = false; Listado 1 obtiene consultando la propiedad DataGridViewCellPaintingEventArgs.State; a la hora de pintar la celda, podremos asignarle un conjunto de colores distinto según el mencionado estado. En el momento de pintar la celda, necesitaremos un objeto de la clase Graphics, que representa el contexto de dispositivo gráfico o superficie sobre la que vamos a dibujar. El acceso a este objeto lo conseguimos gracias a la pro- piedad DataGridViewCellPaintingEventArgs.Graphics, realizando el dibujo de la celda mediante una llamada a su método FillRectangle, que recibe como parámetros el objeto PathGradientBrush para aplicar el fundido de colores, y el rectángulo de la celda, que está en la propiedad DataGridViewCellPaintingEventArgs.CellBounds. El contorno o línea delimitadora de los bordes de la celda será dibujado utilizando el méto- << dnm.plataforma.net private void dgvGrid_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { // comprobar que la fila y columna están dentro del rango // y que la columna corresponde a una de las que vamos // a pintar if (e.ColumnIndex > 0 && e.RowIndex >= 0 && (this.dgvGrid.Columns[e.ColumnIndex].Name == “Color” | this.dgvGrid.Columns[e.ColumnIndex].Name == “ListPrice”)) { // crear un array con las coordenadas // sobre las que aplicaremos los colores con fundido // basadas en la posición y dimensión de la celda Point[] aPuntos = new Point[] { new Point(e.CellBounds.X,e.CellBounds.Y), new Point(e.CellBounds.X, e.CellBounds.Y + e.CellBounds.Height), new Point(e.CellBounds.X + e.CellBounds.Width, e.CellBounds.Y + e.CellBounds.Height), new Point(e.CellBounds.X + e.CellBounds.Width, e.CellBounds.Y)}; PathGradientBrush pgbBrush; Color[] aColores; // // // if { aColores = new Color[] { Color.LightYellow, Color.DarkTurquoise, Color.MediumSpringGreen, Color.LightSteelBlue}; pgbBrush = new PathGradientBrush(aPuntos); pgbBrush.CenterColor = Color.Lavender; pgbBrush.SurroundColors = aColores; DataGridViewCellPaintingEventArgs necesarias para esta operación: el objeto Graphics; la propiedad FormattedValue, más recomendable que su homóloga Value, fundamentalmente para aquellos casos de columnas con valores numéricos o de fecha formateados; CellBounds, como superficie o rectángulo sobre la que dibujar el texto; y finalmente los valores del estilo –propiedad CellStyle–, que contienen el tipo de letra y su color. • Como última acción en el código de este evento, tenemos que asignar el valor true a la propiedad DataGridViewCellPaintingEventArgs.Handled, puesto que es necesario informar al control de que nosotros hemos sido crear el objeto brush con efecto de fundido utilizando una combinación de colores diferente en función de si la celda está o no seleccionada ((e.State & DataGridViewElementStates.Selected) == DataGridViewElementStates.Selected) } else { aColores = new Color[] { Color.BlanchedAlmond, Color.LightSalmon, Color.LightYellow, Color.DarkOrange}; pgbBrush = new PathGradientBrush(aPuntos); pgbBrush.CenterColor = Color.LawnGreen; pgbBrush.SurroundColors = aColores; } // aplicar el objeto brush con el efecto de colores fundidos // y dibujar un borde para el rectángulo de la celda e.Graphics.FillRectangle(pgbBrush, e.CellBounds); <<dotNetManía do Graphics.DrawRectangle, aplicando un color al borde sobre el rectángulo de la celda. Pero esto no es suficiente, ya que solamente hemos dibujado el borde y colores de fondo de la celda. Aún nos queda el texto que representa el valor de la celda, que obtenemos de la propiedad Value o FormattedValue, pertenecientes al parámetro DataGridViewCellPaintingEventArgs del evento. Sin embargo, no podemos utilizar directamente esta propiedad; recordemos que el evento CellPainting nos obliga a realizar manualmente todas las operaciones de dibujo, por lo que deberemos convertir a modo gráfico la cadena a dibujar siguiendo estos pasos: • Tras comprobar que existe realmente un valor a dibujar, tenemos que calcular las dimensiones del texto (de tipo Size) utilizando el método estático TextRenderer.MeasureText, al que pasaremos como parámetro el valor de la celda y el tipo de letra que usaremos para dibujarlo. Para este último, emplearemos el objeto Font situado en el estilo de la columna correspondiente a la celda. • A continuación, empleando el también método estático TextRenderer.DrawText, será cuando realmente dibujemos el texto, pasando como parámetro aquellas propiedades del objeto 29 << dnm.plataforma.net TextRenderer.DrawText(e.Graphics, e.FormattedValue.ToString(), e.CellStyle.Font, e.CellBounds, e.CellStyle.ForeColor, TextFormatFlags.Top); e.Graphics.DrawRectangle( new Pen(Color.DarkMagenta, 3), e.CellBounds); // si la celda tiene valor if (e.Value != null) { // calcular el tamaño del texto Size szTexto; szTexto = TextRenderer.MeasureText( e.Value.ToString(), e.CellStyle.Font); Listado 3 mos dibujando celdas para dos columnas diferentes mediante CellPainting. Supongamos que es necesario aplicar una alineación distinta para cada una de ellas. Esta es una situación que podemos solventar en el evento Load del formulario, asignando a la propiedad Tag de los estilos creados para estas columnas el valor o combinación de valores de TextFormatFlags que necesitemos para establecer la alineación o efectos para el texto. La propiedad DataGridViewCellStyle.Tag es de tipo object, lo cual la convierte en un estupendo “cajón de sas- // dibujar el texto TextRenderer.DrawText(e.Graphics, e.FormattedValue.ToString(), e.CellStyle.Font, e.CellBounds, e.CellStyle.ForeColor); } e.Handled = true; } } Listado 2 los encargados de realizar la operación de dibujo de la celda; de lo contrario, el control hará caso omiso de nuestro código, realizando él solito las operaciones de dibujo. El listado 2 muestra el código del evento CellPainting que acabamos de explicar en los párrafos anteriores. La figura 1 muestra la rejilla resultante de la aplicación de este proceso de dibujo personalizado con CellPainting, donde podemos observar las celdas que hemos pintado tanto en estado normal como seleccionado. <<dotNetManía Cambiando la alineación en el contenido de las celdas 30 El método TextRenderer.DrawText, como acabamos de comprobar, dibuja el texto centrado en la celda de manera predeterminada, pero supongamos que es necesaria una alineación diferente. Para conseguir dicho objetivo, añadiremos Figura 1. Celdas pintadas mediante el evento CellPainting. a DrawText como último parámetro el tipo enumerado TextFormatFlags, cuyos valores podemos utilizar de forma combinada para crear diferentes efectos de formato, alineación, recorte de fuente, etc. Por ejemplo, si queremos que el texto de la celda quede alineado a la parte superior de la misma, utilizaremos el código del listado 3. Pero en el DataGridView que estamos desarrollando para este ejemplo esta- tre” para almacenar valores de cualquier tipo, en función del problema a resolver en las más diversas situaciones. Por lo tanto, como hemos dicho, si para cada estilo asignamos por separado los valores de alineación a la propiedad Tag, posteriormente la aplicación de dichos valores en CellPainting se simplifica enormemente cuando dibujamos el texto con el método DrawText, como vemos en el listado 4. << dnm.plataforma.net private void Form1_Load(object sender, EventArgs e) { //.... styListPrice.Tag = TextFormatFlags.Right | TextFormatFlags.VerticalCenter; //.... styColor.Tag = TextFormatFlags.Left | TextFormatFlags.VerticalCenter; //.... } zeColumnsMode. Esta acción tiene como efecto que el usuario pueda cambiar el ancho de las columnas, y al reducir su tamaño, el texto de estas quede oculto en algunos casos. El efecto conseguido por el recorte del texto puede no resultar muy agradable, por lo que si aplicamos el valor TextFormatFlags.WordEllipsis, agregando este efecto a los demás ya existentes que se utilizan en el método DrawText, el resultado será la visualización de puntos suspensivos en aquellas celdas que no puedan mostrar su contenido al completo. Este efecto lo podemos ver en la figura 3. private void dgvGrid_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { //.... TextRenderer.DrawText(e.Graphics, e.FormattedValue.ToString(), e.CellStyle.Font, e.CellBounds, e.CellStyle.ForeColor, (TextFormatFlags)e.CellStyle.Tag); //.... } Figura 3. Puntos suspensivos en las celdas que no muestran su texto al completo. Listado 4 En la figura 2 podemos apreciar el resultado de esta técnica para alinear los valores. Y ya para terminar con el tipo TextFormatFlags, vamos a comentar otro efecto realmente curioso. El valor NoClipping de esta enumeración tiene como finalidad no recortar los extremos del texto cuando reducimos el tamaño de la celda. Si combinamos este valor con HorizontalCenter, como muestra el listado 5, obtendremos el interesante efecto de la figura 4, donde los extremos de texto de la celda “invaden” las celdas adyacentes. Figura 2. Pintando celdas con distinta alineación desde CellPainting. <<dotNetManía Otros efectos sobre el contenido 32 Vamos a continuación a introducir una nueva variante en este escenario de trabajo. Imaginemos que no utilizamos el ajuste automático de anchura de columnas para el control, por lo que borramos la línea de código que hace uso de la propiedad DataGridView.AutoSi- TextRenderer.DrawText(e.Graphics, e.FormattedValue.ToString(), e.CellStyle.Font, e.CellBounds, e.CellStyle.ForeColor, TextFormatFlags.HorizontalCenter | TextFormatFlags.NoClipping); Listado 5 << dnm.plataforma.net CellPainting en las cabeceras de columna. Indicando el orden de los registros con una imagen propia Para aplicar el evento CellPainting en las cabeceras del control, emplearemos la misma lógica que en las celdas de datos, pero debemos tener en cuenta que el comportamiento de una cabecera, cuando el usuario hace clic sobre ella, consiste en ordenar sus celdas mostrando además un pequeño icono que indica el orden establecido. Si aplicamos una operación de dibujo personalizado a la celda de cabecera con CellPainting, al hacer clic en ella para ordenar sus datos éstos efectivamente se ordenarán, pero el icono informativo del tipo de orden no se mostrará, ya que cuando realizamos el dibujo de una celda con este evento, como ya sabemos, la responsabilidad de pintar hasta el último elemento necesario recae sobre el programador. Dado que el código a utilizar para pintar una celda de cabecera es muy parecido al de una celda normal de datos, dentro del listado 6, en lo que se refiere al código del evento CellPainting, nos centraremos sólo en aquellos aspectos aplicables para este caso concreto. Podemos ver, en primer lugar, la necesidad de comprobar que el índice de la columna sea mayor o igual a cero, el de la fila menor de cero, y el nombre de la columna a dibujar corresponda a la que necesitamos pintar de forma personalizada. <<dotNetManía Figura 4. Los extremos del texto en las celdas no se recortan. A continuación, debemos averiguar el nombre de la columna pulsada, disponible en la variable sCabeceraPulsada, que hemos declarado con ámbito a nivel de la clase del formulario. Dicha variable la asignamos en otro evento: ColumnHeaderMouseClick, provocado cuando el usuario hace clic en una cabecera de columna. Después de dibujar el título de la celda alineado a la izquierda, comprobaremos si la columna va a ordenarse en alguna dirección. En caso afirmativo, disponemos de dos imágenes agregadas al proyecto como recursos incrustados (este valor lo establecemos en la ventana de propiedades de la imagen, dentro de la propiedad “Acción de generación”). Según el orden, obtendremos la imagen correspondiente, asignándola a una variable de tipo Bitmap. No obstante, es posible que la celda necesite dibujarse, pero no porque se haya pulsado la cabecera, en cuyo caso la propiedad DataGridView.SortOrder contendrá el valor None, y la variable Bitmap estará a null. Por dicho motivo, tenemos que comprobar que exista realmente una imagen a dibujar, y en ese caso, dibujarla en la parte derecha de la celda utilizando el método Graphics.DrawImage, calculando la posición en la cual dibujar a partir del tamaño de la propia imagen y las propiedades del rectángulo de la cabecera. 33 << dnm.plataforma.net string sCabeceraPulsada = string.Empty; //.... private void Form1_Load(object sender, EventArgs e) { //.... this.dgvGrid.EnableHeadersVisualStyles = false; // crear un estilo para las cabeceras del control DataGridViewCellStyle styCabecera = new DataGridViewCellStyle(); styCabecera.BackColor = Color.BlanchedAlmond; styCabecera.ForeColor = Color.DarkBlue; styCabecera.Alignment = DataGridViewContentAlignment.MiddleLeft; styCabecera.Font = new Font(“Century Schoolbook”, 10, FontStyle.Bold); styCabecera.Padding = new Padding(10); Figura 5. Cabecera de columna con dibujo personalizado de icono de orden y fundido de colores. La figura 5 muestra el control en ejecución, donde podemos observar la celda de cabecera con las operaciones que acabamos de describir. CellPainting en las cabeceras de fila. Indicando el número de fila a todo color <<dotNetManía Y si hemos podido pintar con alegres y gráciles colorines una cabecera del control, las cabeceras de las filas no van a ser menos, ni se van a librar de nuestro arrebato artístico, así que tomando nuestros botes de pintura y pinceles digitales, pongámonos a trabajar. La técnica que vamos a emplear, como puede intuir el lector, será muy similar a los otros casos anteriores, con la salvedad de que ahora vamos a dibu- 34 Al realizar el dibujo de una celda mediante CellPainting, la responsabilidad de pintar hasta el último detalle recae sobre el programador this.dgvGrid.ColumnHeadersDefaultCellStyle = styCabecera; // ampliar la anchura de la columna // sobre la que vamos a dibujar la cabecera this.dgvGrid.Columns[“ProductKey”].Width += 40; } // cada vez que hacemos clic en la cabecera // guardamos el nombre de la columna pulsada private void dgvGrid_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) { sCabeceraPulsada = this.dgvGrid.Columns[e.ColumnIndex].Name; } private void dgvGrid_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { // comprobar si la cabecera a pintar es la que necesitamos if (e.ColumnIndex >= 0 && e.RowIndex < 0 && this.dgvGrid.Columns[e.ColumnIndex].Name == “ProductKey”) { //.... // dibujar el título de la cabecera // alineado a la izquierda TextRenderer.DrawText(e.Graphics, e.FormattedValue.ToString(), e.CellStyle.Font, e.CellBounds, e.CellStyle.ForeColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter); // si la cabecera pulsada es la que necesitamos, // en función del tipo de ordenación, // obtener la imagen del recurso incrustado en el proyecto Bitmap bmpImagen = null; if (sCabeceraPulsada == “ProductKey”) { switch (this.dgvGrid.SortOrder) { case SortOrder.Ascending: bmpImagen = << dnm.plataforma.net case SortOrder.Descending: bmpImagen = new Bitmap(GetType(), “FlechaAbajo.png”); break; } } // pintar la imagen en la celda de la cabecera // si realmente se ha establecido un orden if (bmpImagen != null) { e.Graphics.DrawImage(bmpImagen, e.CellBounds.Right – (bmpImagen.Width + e.CellStyle.Padding.Left), e.CellBounds.Y + e.CellStyle.Padding.Top); } e.Handled = true; } } Listado 6 private void dgvGrid_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { // si la celda a pintar es cabecera de fila if (e.ColumnIndex < 0 && e.RowIndex >= 0) { // calcular el número a pintar en la celda int nNumeroFila = e.RowIndex + 1; //.... // crear la fuente a usar para dibujar el número Font oFont = new Font(“Comic Sans MS”, 12, FontStyle.Italic); // calcular el tamaño del texto Size szTexto = TextRenderer.MeasureText(nNumeroFila.ToString(), oFont); // dibujar el número TextRenderer.DrawText(e.Graphics, nNumeroFila.ToString(), oFont, e.CellBounds, e.CellStyle.ForeColor); e.Handled = true; } } Listado 7 jar el número de cada fila, por lo que tendremos que calcular dicho valor basándonos en la propiedad DataGridViewCellPaintingEventArgs.RowIndex, y comprobar que la celda sobre la que vamos a realizar las operaciones pertenece a una fila; o lo que es lo mismo, al tomar el parámetro DataGridViewCellPaintingEventArgs del evento CellPainting, la propiedad ColumnIndex deberá ser menor que cero, y la propiedad RowIndex mayor o igual que cero. Los efectos de colores fundidos y cálculo de coordenadas para pintar el objeto PathGradientBrush serán los mismos que en los anteriores ejemplos, por lo que el cambio en este caso concreto consistirá en crear un tipo de letra explícitamente para dibujar el número en la celda. Por este motivo, en el listado 7 se exponen aquellas instrucciones que representan cambios con respecto a los anteriores ejemplos. Para comprobar la aplicación de este efecto sobre esta parte del control, veamos la figura 6. Figura 6. Personalizando el dibujo de las cabeceras de fila. Acabando la pintura Llegamos al punto final de este artículo, en el que hemos realizado un repaso del evento CellPainting del control DataGridView, como medio para aplicar ciertos efectos avanzados de presentación sobre las celdas del control a fin de lograr un resultado más agradable a la vista de nuestros usuarios. Que ustedes lo disfruten. <<dotNetManía new Bitmap(GetType(), “FlechaArriba.png”); break; 35 plataforma.net Alberto Población Más sobre seguridad de acceso a código En una entrega anterior (dotNetManía nº 41) presentamos los fundamentos de la Seguridad de acceso a código (Code Access Security, CAS) en .NET Framework, y describimos cómo el CLR determina los permisos del código y cómo se pueden manipular desde las herramientas administrativas los permisos concedidos a cada ensamblado. En esta entrega veremos cómo se pueden solicitar, manipular y limitar estos permisos desde dentro de nuestro código. Atributos para solicitud y rechazo de permisos Un primer paso que podemos dar en nuestros programas es el de “decorar” el código fuente con una serie de atributos en los que se especifican los requisitos que tiene el ensamblado en cuanto a los permisos que necesita para poder funcionar. Cuando especificamos los requisitos de seguridad mediante atributos, se dice que estamos haciendo operaciones de seguridad declarativas, en contraposición a las que se realizan mediante sentencias de código ejecutable, que se denominan imperativas. En su modalidad más simple, la solicitud de permisos puede tener este aspecto: Alberto Población lleva 27 años desarrollando software. Cuenta entre otras con las certificaciones MCSE, MCDBA, MCITP, MCSD, MCPD y MCT, además de ser MVP de C#. En la actualidad trabaja como consultor independiente, dedicándose principalmente a la formación, asesoramiento y desarrollo de aplicaciones. using System.Security.Permissions; ... [assembly: UIPermission(SecurityAction.RequestMinimum, Window=UIPermissionWindow.AllWindows)] Estos atributos, que afectan a todo el ensamblado, se pueden introducir en cualquiera de los fuentes que se compilan para formar dicho ensamblado; pero es costumbre, para facilitar su locali- zación, agruparlos dentro del archivo AssemblyInfo.cs (o .vb). En el ejemplo anterior hemos utilizado un permiso del tipo UIPermission, es decir, una solicitud de permiso de interfaz de usuario. En los argumentos hemos especificado SecurityAction.RequestMinimum, indicando que el programa necesita como mínimo este permiso para poder funcionar. Si las políticas de seguridad del sistema no concediesen a este ensamblado los permisos que hemos señalado como “mínimos”, el ensamblado no llegaría a cargarse, y el sistema mostraría directamente un error de seguridad, sin siquiera arrancar el programa. El parámetro Window=UIPermissionWindow.AllWindows especifica en mayor detalle el tipo concreto de UIPermission que estamos solicitando. Para cada subtipo de Permission, los argumentos disponibles son diferentes y permiten matizar las características y alcance del permiso correspondiente. Cabe señalar que también es posible solicitar de golpe un conjunto de permisos completo. Por ejemplo, para solicitar el conjunto “Full Trust”: [assembly: RegistryPermission( SecurityAction.RequestMinimum, Name=”FullTrust”)] << dnm.plataforma.net [assembly: FileIOPermission( SecurityAction.RequestOptional, Unrestricted=true)] [assembly: RegistryPermission( SecurityAction.RequestRefuse, Unrestricted = true)] Con el primero de estos atributos estamos indicando al sistema de seguridad que deseamos utilizar el permiso de FileIO si las políticas de seguridad lo permiten para este ensamblado, pero que el programa puede funcionar sin este permiso. Esto puede ser útil, por ejemplo, para un programa que grabe una bitácora (log) de sus operaciones en un archivo en disco, pero que en caso de no tener ese permiso puede seguir funcionando; eso sí, sin grabar el log. El segundo atributo expresa que no deseamos disponer de permiso de acceso al Registro de Windows, incluso aunque las políticas de seguridad lo consientan para nuestro ensamblado. De esta forma garantizamos que el programa nunca pueda modificar el Registro, incluso aunque presente un mal funcionamiento o un uso indebido de alguna función de librería que pudiera realizar ese tipo de operación. La asignación final de permisos que recibe el ensamblado consiste en los Mínimos, más los Opcionales que permita la política de seguridad, menos los Rechazados. Hay que señalar que, en caso de que no se solicite ningún permiso opcional, el sistema interpreta que se solicita “Full Trust” como permiso opcional, y por tanto se conceden todos los permisos que permita la política, salvo los rechazados expresamente. Por este motivo, es buena costumbre incluir un atributo como el siguiente: [assembly: FileIOPermission( SecurityAction.RequestOptional, Unrestricted=false)] Con esto indicamos que solicitamos como Opcional “ningún permiso”, con lo que ya no se aplica lo indicado en el párrafo anterior, y los únicos permisos concedidos son los que solicitemos expresamente mediante el resto de los atributos. De esta forma, el programa no recibe ningún permiso superfluo. (“Ensamblado 2”) que graba ciertos datos en disco. Este ensamblado, al igual que el anterior, habrá recibido los permisos que le correspondan; por ejemplo, podría tener permiso de escritura en disco. Para realizar físicamente la grabación, esta DLL utiliza las rutinas contenidas en el espacio de nombres System.IO, que se encuentran compiladas dentro de una de las DLL que se suministran con .NET Framework, y que en la figura hemos llamado “Ensamblado 3”. Solicitud de permisos (“Demand”) Hemos visto que un ensamblado puede solicitar y recibir una serie de permisos. Los permisos que ha recibido el ensamblado entrarán en juego en el momento en que el código que se ejecuta realice una operación que requiera dichos permisos. ¿Cómo se determinan y se controlan estas operaciones? Veámoslo, apoyándonos en la figura 1. Supongamos que tenemos un programa ejecutable, que en la figura denominamos “Ensamblado 1”, que conforme con las políticas del sistema ha recibido permiso de ejecución pero no de escritura en disco. Este programa realiza una llamada a una DLL Figura 1 Esta librería, en última instancia, tendrá que utilizar los servicios de invocación a la plataforma (P/Invoke) para Instrucciones de control de seguridad Solicitar permisos Demand Afirmar permisos Assert Restricción de permisos Deny PermitOnly Desactivar llamadas en la pila RevertAssert RevertDeny RevertPermitOnly RevertAll Comparar permisos IsSubsetOf Combinación de permisos Union Intersect <<dotNetManía De forma similar a la solicitud de permisos mínimos, se pueden añadir solicitudes de permisos Opcionales y Rechazados: 37 << dnm.plataforma.net using System.Security.Permissions; // ... public void Escribir(string fichero) { FileIOPermission permiso = new FileIOPermission( FileIOPermissionAccess.Write, fichero); try { permiso.Demand(); // Aquí, si la solicitud tiene éxito, // usamos P/Invoke para llamar a la API } catch (SecurityException ex) { // Si falla el Demand(), se produce esta excepción } } <<dotNetManía Listado 1 38 llamar a las API de Windows que realizan la grabación mediante código no manejado. Antes de hacer el salto a dicho código no manejado, el programa hace una llamada al código de seguridad de .NET que se denomina “solicitud de permiso” (“Demand”). En el listado 1 tenemos un ejemplo que muestra una solicitud de este tipo. Cuando se ejecuta el Demand(), el motor de seguridad realiza un recorrido por la pila de llamadas (stack walk), comprobando si todos los llamantes de esta rutina tienen el permiso solicitado. En el ejemplo de la figura 1, la solicitud sube en primer lugar al Ensamblado 2, que efectivamente tenía permiso de escritura, con lo que la solicitud continúa subiendo por la pila. Al llegar al Ensamblado 1, el CLR determina que dicho ensamblado no tiene permiso de escritura, por lo que se produce una excepción de seguridad y la escritura no llega a realizarse. El resultado final es que no se produce ninguna escritura en disco, a pesar de que las DLL que contienen instrucciones de grabación tienen permiso para ello, debido a que el llamante inicial tiene prohibida dicha escritura por las políticas de seguridad de .NET. Estas solicitudes también se pueden hacer de forma declarativa en lugar de imperativa, a nivel de clase o de método: [FileIOPermission( SecurityAction.Demand, Write = “C:\\Fichero”)] public class ClaseConPermiso {...} Afirmación de permisos (“Assert”) Vayamos más allá y supongamos que realmente sí que deseamos realizar la grabación anterior. Por ejemplo, el Ensamblado 2 podría contener unas rutinas de registro en bitácora (logging) que graben en un archivo una traza de las operaciones realizadas, y deseamos que esa traza quede grabada siempre que un ejecutable llame a esta librería, aunque el ejecutable en sí no tenga permiso para escribir en disco. Esto se logra mediante la operación llamada “Assert”, tal como muestra el ejemplo del listado 2. Volviendo al ejemplo de la figura 1, y suponiendo que el Assert() se ha introducido en el Ensamblado 2, cuando se produce el Demand() en el Ensamblado 3 y “sube” a la trama anterior de la pila, se encuentra que en dicha trama se ha realizado una afirmación del permiso solicitado, y en consecuencia se da dicho permiso por concedido, teniendo éxito el Demand() sin llegar a subir hasta el Ensamblado 1. private void GrabarTraza() { const string fichero = C:\\log.txt”; FileIOPermission permiso = new FileIOPermission( FileIOPermissionAccess.Write, fichero); permiso.Assert(); // Aquí se hace la grabación FileIOPermission.RevertAssert(); } Listado 2 Lógicamente, este proceso solo tendrá éxito si la política de seguridad concede el permiso solicitado al ensamblado que realiza el Assert. Solo puede haber un único Assert activo por cada trama de la pila. Una vez que el Assert ya no se necesita, se desactiva mediante RevertAssert(), como se ve en el ejemplo del listado 2. Hay que actuar con precaución al escribir ensamblados que utilicen el Assert, ya que por esta vía se pueden abrir agujeros de seguridad. Por ejemplo, en el listado 2 hemos especificado como const string el nombre del fichero en el que se graba el log. Si en lugar de eso hubiéramos aceptado este fichero como parámetro del método, el programa llamante (que, recordemos, no tiene permisos para grabar en disco) podría pasar por esta vía una ruta cualquiera y “engañar” al sistema de seguridad consiguiendo grabar en disco un archivo de su elección, aprovechándose de los permisos que tiene concedidos el Ensamblado 2. Rechazo de permisos (“Deny”) La operación “Deny” funciona del modo contrario que Assert. Cuando ejecutamos un Deny(), estamos forzando que se produzca una excepción cuando el código más abajo en la pila realice un Demand() del permiso objeto del Deny, incluso aunque el ensam- << dnm.plataforma.net blado llamante sí que tenga el permiso en cuestión. El ejemplo del listado 3 rechaza el permiso de utilizar reflexión sobre miembros no visibles de un tipo. public void Metodo() { ReflectionPermission permiso = new ReflectionPermission( ReflectionPermissionFlag. TypeInformation); permiso.Deny(); // Usar reflexión para acceder a // miembros públicos ReflectionPermission.RevertDeny(); } Prueba de los programas bajo condiciones de seguridad restringida Cuando estamos desarrollando programas, normalmente los ejecutables se crean sobre nuestro disco local y desde ahí los ejecutamos. La política de seguridad predeterminada les otorga entonces el conjunto de permisos “Full Trust”. Por lo tanto, al ejecutarlos no ejercitamos las distintas limitaciones de seguridad a las que se refiere este artículo. Si deseamos probar y depurar nuestros programas bajo condiciones de seguridad limitada, podemos crear una carpeta en nuestro disco y asignar a los archivos cargados desde esa carpeta una política restrictiva, añadiendo el atributo “Exclusive”, para que no reciban además los permisos predeterminados. Una forma de asignar estos permisos consiste en utilizar el comando CASPOL: md c:\pruebas caspol -ag 1 -url file:///C:/pruebas/* Internet -n Pruebas -exclusive on Para probar nuestro programa, copiaremos el ejecutable a esta carpeta y lo ejecutaremos desde ahí, con lo cual se verá limitado a los permisos asignados, que en el ejemplo anterior son los de la Zona Internet. [PermissionSet( SecurityAction.LinkDemand, Name = “FullTrust”)] public void Metodo(...){...} validez de su código en dichos entornos mediante el atributo AllowPartiallyTrustedCallers: Listado 3 [assembly: AllowPartiallyTrustedCallers] Si este código se introdujera en el Ensamblado 2 de la figura 1, y detrás del Deny se llamara a una subrutina del Ensamblado 3 que tratara de usar reflexión sobre miembros privados de una clase, se produciría una excepción de seguridad, aún en el caso de que tanto el Ensamblado 3 como el 2 tuvieran concedido dicho permiso. “LinkDemand” La operación “LinkDemand” opera de forma similar al Demand que hemos mencionado más arriba, con la diferencia de que LinkDemand() solo comprueba el llamante inmediato, en lugar de recorrer toda la pila comprobando si la totalidad de los llamantes tienen el permiso solicitado. Por ejemplo, para comprobar que el llamante tiene “Full Trust”: Adicionalmente, el Demand recorre la pila cada vez que es invocado, debido a que los llamantes podrían ser distintos, mientras que el LinkDemand se resuelve en tiempo de compilación Just-In-Time (JIT), por lo que solo se comprueba una vez. El atributo AllowPartiallyTrustedCallers Todo ensamblado que tiene un nombre fuerte (strong name) recibe implícitamente un LinkDemand del conjunto de permisos Full Trust. Esto provoca el que dichos ensamblados no puedan ser llamados desde programas que no tengan confianza completa. Si el programador ha tenido en cuenta al desarrollar el ensamblado las implicaciones de seguridad de los entornos que tienen confianza parcial, puede declarar expresamente la La consecuencia de aplicar este atributo es que se elimina el mencionado LinkDemand y el ensamblado deja de requerir que sus llamantes tengan permisos Full Trust. Conclusión Cuando escribamos librerías que utilicen llamadas a código no gestionado, y sea previsible que éstas puedan ser llamadas desde código que no tenga confianza completa, es recomendable que introduzcamos dentro las peticiones de permisos (con “Demand”) que sean oportunas de conformidad con las operaciones que realice dicho código no manejado, a fin de evitar que los programas que llamen a nuestra librería y no tengan confianza completa puedan aprovecharse de ella para saltarse las políticas de seguridad. La librería de MSDN contiene la referencia completa de las clases que manejan la Seguridad de acceso a código. Véanse estos enlaces: http://msdn.microsoft.com/library/SPA/cpguide/html/cpconsecurecodingguidelines.asp http://msdn2.microsoft.com/es-es/library/system.security(VS.80).aspx <<dotNetManía Documentación 39 plataforma.net Daniel Seara Herramientas genéricas para los componentes: ficheros y recursos Siguiendo con la idea de las generalizaciones en componentes expuesta en el número anterior, en este artículo veremos algunos otros ejemplos que pueden resultarle interesantes. Manipulando archivos (o ficheros) Más tarde o más temprano, nuestros componentes necesitarán acceder a archivos físicos en disco. Consideremos entonces una clase que encapsule dichas acciones: FileIO. En este caso, las acciones serán inmediatas, sin mucha cosa que hacer más que la tarea específica. Para facilitar el acceso, hagamos que los métodos de esta clase sean accesibles directamente, sin necesidad de instanciar la misma. Para ello, nos aseguraremos de que la clase no sea heredable, utilizando NotInheritable como modificador en la declaración de la clase, y tenga un único constructor privado, para que no se puedan crear instancias. Public NotInheritable Class FileIO Private Sub New() End Sub End Class Public Shared Function GetFileContent( _ ByVal path As String) As String Try ‘ Se evalúa si el usuario tiene permiso de acceso Dim permission As New _ System.Security.Permissions.FileIOPermission(_ System.Security.Permissions.FileIOPermissionAccess.Read,_ path) permission.Demand() ‘ Mediante using, nos aseguramos de que se libere ‘ adecuadamente el recurso Using fi As New System.IO.StreamReader(path, _ System.Text.Encoding.Default) Dim s As String = fi.ReadToEnd fi.Close() Return s End Using Catch ex As Exception Throw Finally End Try End Function Listado 1 Leyendo contenido del disco Daniel Seara es mentor de Solid Quality Mentors y director del área de desarrollo .NET. Es MVP desde 2003 y ponente habitual de INETA y Microsoft. Lo importante en este caso es: 1. Asegurarse de que el usuario tiene derechos de lectura sobre el elemento requerido. 2. Disponer adecuadamente del recurso de acceso a disco. Es muy útil disponer de métodos para recuperar y almacenar información privada del usuario para cada aplicación. Para ello, es más seguro utilizar IsolatedStorage. Y de una forma muy similar, implementamos escrituras (listado 2). << dnm.plataforma.net El código importa el espacio System.IO.IsolatedStorage para facilitar el acceso a los objetos definidos en él. ][ NOTA Es importante tener en cuenta que se pueden duplicar estas funciones para que utilicen arrays de bytes u objetos MemoryStream para manipular datos binarios. ] Public Shared Function GetPrivateContent( ByVal name As String) _ As String Try Using isoFile As _ IO.IsolatedStorage.IsolatedStorageFile = _ IsolatedStorageFile.GetStore(IsolatedStorageScope.User _ Or IsolatedStorageScope.Assembly _ Or IsolatedStorageScope.Domain, Nothing, Nothing) Using isoStream As New IsolatedStorageFileStream( _ name, IO.FileMode.Open, isoFile) Using Reader As New IO.StreamReader(isoStream) Dim sReturn As String = Reader.ReadToEnd Reader.Close() isoStream.Close() isoFile.Close() Return sReturn End Using End Using End Using Catch ex As Exception Throw End Try End Function Listado 2 Listado 3 Otro elemento interesante a generalizar es la obtención de recursos, tan- Public Enum SourceAssemblyEnum_ As Integer CallerAssembly InitialAssembly End Enum Y, nuevamente, una clase que permita acceder directamente los métodos, sin necesidad de instanciarla. Public NotInheritable Class_ Resources Shared Sub New() End Sub End Class [ ] NOTA En este caso, el constructor es Shared. La diferencia es que, si necesitáramos hacer algo la primera vez que se utiliza un método de esta clase, podríamos hacerlo allí. No es este el caso, pero quería dejar claro cómo se hace. Public Shared Sub WritePrivateContent( _ ByVal name As String, ByVal content As String) Using isoFile As IO.IsolatedStorage.IsolatedStorageFile = _ IsolatedStorageFile.GetStore( _ IsolatedStorageScope.User _ Or IsolatedStorageScope.Assembly _ Or IsolatedStorageScope.Domain, _ Nothing, Nothing) Using isoStream As New IsolatedStorageFileStream( _ name, IO.FileMode.Create, isoFile) Using writer As New IO.StreamWriter(isoStream) writer.Write(content) writer.Close() isoStream.Close() isoFile.Close() End Using End Using End Using End Sub Recursos pleja, puede que sean del componente que se está ejecutando o del proceso que lanza la ejecución. Definamos un enumerador que nos permita identificar de dónde queremos extraer los recursos: to sean textos como de formato binario. En muchas oportunidades necesitaremos de ellos y, cosa aún más com- Utilizando el enumerador podremos identificar de dónde obtener el recurso. Necesitamos entonces el nombre del mismo y ya podremos hacerlo (siempre, los recursos se obtienen como un stream) (listado 4). Una vez que obtenemos el stream, convertirlo a texto es simplemente transformarlo de acuerdo a la codificación, que en general es la predeterminada en el proceso (listado 5). <<dotNetManía [ NOTA 41 << dnm.plataforma.net Public Shared Function GetResourceStream( _ ByVal name As String, _ Optional ByVal Source As SourceAssemblyEnum = _ SourceAssemblyEnum.CallerAssembly) _ As System.IO.Stream Dim ass As System.Reflection.Assembly = Nothing Select Case Source Case SourceAssemblyEnum.CallerAssembly ass = System.Reflection.Assembly.GetCallingAssembly Case SourceAssemblyEnum.InitialAssembly ass = System.Reflection.Assembly.GetEntryAssembly End Select ‘ La propiedad FullName retorna varios datos. ‘ De ellos, el primero es el nombre del ensamblado, ‘ que es lo que necesitamos Dim sName As String = ass.FullName.Split(“,”c)(0) Dim str As System.IO.Stream = _ ass.GetManifestResourceStream( _ String.Format(“{0}.{1}”, sName, name)) ‘ Si el recurso no existe no se obtiene nada ‘ Por lo tanto, sigue siendo Nothing If str Is Nothing Then ‘ Esta excepción hereda de ‘ Solid.Tools.ExceptionHandler.BaseException Throw New KeyNotExistException End If Return str End Function Listado 4 <<dotNetManía Public Shared Function GetResourceString( _ ByVal name As String, _ Optional ByVal source As SourceAssemblyEnum = _ SourceAssemblyEnum.CallerAssembly) As String 42 ‘ Utiliza GetResourceStream para obtener el recurso Dim str As System.IO.Stream = _ GetResourceStream(name, source) With str ‘ Se obtienen todos los bytes Dim bytes(CInt(.Length)) As Byte .Read(bytes, 0, CInt(.Length - 1)) Dim textConverter As System.Text.Encoding = _ System.Text.Encoding.Default Try ‘ Se transforman a cadena de caracteres Return textConverter.GetString(bytes) Catch ex As Exception ‘ Hereda de ‘ Solid.Tools.ExceptionHandler.BaseException Throw New ResourceNotFoundException(ex) End Try End With End Function Listado 5 Es muy útil disponer de métodos para recuperar y almacenar información privada del usuario para cada aplicación. Para ello, es más seguro utilizar IsolatedStorage ¿Y qué pasa con My? Sí, claro, obviamente puede utilizarse sin problemas, pero las funciones anteriores sirven para obtener cualquier recurso, no solo los incluidos en el proyecto actual (ensamblado actual). Y hablando de My, les dejo un pequeño procedimiento para cargar los iconos que necesite un formulario en controles ImageList desde los recursos de la aplicación. En el ejemplo se asume que toda imagen cuyo nombre termine en “16” es para un determinado ImageList (podría repetirse para “32”, etc. para cargar distintos ImageList). Sub LoadImageLists() Dim myRes As Resources.ResourceSet = _ My.Resources.ResourceManager.GetResourceSet( _ System.Threading.Thread.CurrentThread.CurrentUICulture,_ False, _ True) Dim myEnum As IDictionaryEnumerator = _ myRes.GetEnumerator() Do While myEnum.MoveNext If myEnum.Key.ToString.EndsWith(“16”) Then img16.Images.Add( _ myEnum.Key.ToString.ToUpper.Replace(“16”, “”), _ System.Drawing.Icon.FromHandle( _ CType(myEnum.Value, Drawing.Bitmap).GetHicon)) End If Loop End Sub Listado 5 Y basta por ahora. Espero en la próxima comenzar con algunas cosas algo más complejas. ¡Saludos! << dnm.inicio inicio Guillermo «Guille» Som Depuración en .NET El depurador que lo depure... recibirá ayuda del CLR Guillermo “Guille” Som Es Microsoft MVP de Visual Basic desde 1997. Es redactor de dotNetManía, mentor de Solid Quality Iberoamericana, tutor de campusMVP, miembro de Ineta Speakers Bureau Latin America, y autor de los libros “Manual Imprescindible de Visual Basic .NET” y “Visual Basic 2005”. http://www.elguille.info La crispación a la que me refería antes se debe a que con las primeras dos versiones de Visual Studio para .NET, cuando depurábamos una aplicación y deteníamos (o se detenía) la ejecución del programa, normalmente porque se producía un error, lo primero que querías hacer era solucionar la causa del error, y para solucionarlo lo habitual era que modificaras el código. Y aquí es cuando empezaban los problemas. Con la versión inicial (llamémosla Visual Studio 2002), no podías modificar nada del código durante la depuración. Si tus antecedentes de programador eran porque usabas Visual Basic 6.0, esa crispación llevaba implícita una implementación de ICabreante (ver dotNetManía nº 16 y 18 para saber más sobre las interfaces), y es que en Visual Basic 6.0 la depuración era muy cómoda; éste permitía modificar el código, cambiar por dónde debía continuar la ejecución y otras facilidades que resultaban útiles a la hora de realizar esa tarea tan, digamos, desagradable. La excusa que nosotros mismos nos poníamos era que “bueno, lo acepto, ya que en Visual Basic 6.0 la ejecución es sobre código casi interpretado y .NET debe hacerlo sobre código compilado, por tanto... acepto pulpo como animal de compañía”, y... ¡te tenías que aguantar! ¡Qué remedio! Después llegó Visual Studio 2003, y la cosa cambió un poco; no mucho, la verdad, pero al menos permitía (y sigue permitiendo) modificar el código. El problema es que esos cambios no serían tenidos en cuenta hasta la próxima vez; es decir, para que fuesen aplicados esos cambios tenías que detener la depuración (o parar la ejecución, que para el caso es lo mismo) y empezar de nuevo. La interfaz que definía esta segunda versión de Visual Studio era IDesesperante; pero ya casi te habías acostumbrado y casi no la implementabas. Y entonces empezaron los rumores: Visual Studio 2005 (por entonces conocido como Whidbey) tendría algo que los programadores de Visual Basic pre-.NET ya tenían desde hacía años: Edit & Continue (editar y continuar). ¡Bien! ¡Una buena noticia! Pero la noticia no solo era buena, sino fabulosa. Esa característica de editar y continuar estaría implementada en el propio corazón de .NET: el CLR. Esto suponía que todos los lenguajes de .NET se beneficiarían de esa característica. Y lo mejor de todo es que si el motor de ejecución permitiría detener la ejecución, hacer cambios y seguir ejecutando la aplicación, lo haríamos sobre código compilado; es decir, todo el proceso sería más fiable que si fuese interpretado o simulado por el entorno de desarrollo, que era lo que en un principio parecía que iba a ocurrir (inicialmente se rumoreaba que solo iba a ser posible usarlo en Visual Basic). Por fin salió a la calle Visual Studio 2005, y pudimos comprobar que era cierto: podemos detener la <<dotNetManía La depuración es una de esas cosas que todos hacemos, o deberíamos hacer, y que a nadie le gusta tener que hacer; no porque no sea necesaria, sino porque al final terminabas fatal de los nervios cuando la depuración la realizabas con versiones anteriores de Visual Studio para .NET; por suerte, esto ya no es así con Visual Studio 2005. En esta serie de dos artículos mostraremos las principales posibilidades que este último entorno pone a nuestro alcance para facilitarnos la depuración de nuestros programas. 43 << dnm.inicio ejecución de la aplicación, hacer cambios en el código fuente y seguir ejecutando sin tener que volver a empezar de cero. Y los que habitualmente usábamos Visual Basic 6.0 incluso vimos muchas mejoras, ya que el entorno de Visual Studio 2005 nos permite hacer ciertos cambios en el código que no podíamos hacer con VB6. Pero no voy a seguir haciendo comparaciones con Visual Basic 6.0; me voy a centrar en qué es lo que podemos hacer y también en lo que no podemos hacer (ya que no podemos hacer todo lo que se nos podría antojar: debemos tener en cuenta que todo el proceso se realiza en tiempo de ejecución y durante ese tiempo, el CLR debe almacenar el estado de la ejecución, almacenar en la pila lo que está ejecutando y otras muchas comprobaciones más, sobre todo cuando se produce una excepción y hay un bloque try/catch de por medio). Pero no empecemos con las pegas, veamos los beneficios y ya iremos encontrándonos con las cosas que podemos y no podemos hacer en nuestro camino hacia la tarea tediosa, pero necesaria de conseguir que nuestras aplicaciones estén libres de fallos. Los previos para la depuración Cuando vamos a depurar aplicaciones con Visual Studio 2005, en realidad no tenemos que hacer casi nada antes, pero al menos debemos permitir la depuración. Para permitir la depuración debemos ejecutar nuestro código en modo Debug, ya que, (salvo que usemos la versión Express) todos los proyectos de Visual Studio 2005 permiten dos modos de compilación y ejecución: Debug y Release. Por regla general, (salvo que la hayamos ocultado), esas opciones están en la barra de herramientas (botonera) de la parte superior del entorno integrado, como podemos ver en la figura 1. hemos incluido código de gestión de la excepción en el bloque correspondiente a la parte catch. Pero el incluir un try con su correspondiente catch cuando estamos depurando puede que no nos permita hacer todo lo que nos gustaría hacer, ya que si tenemos un bloque try/catch el error será interceptado y no sabremos a ciencia cierta dónde se produjo... o casi; al menos en un proyecto grande, ya que ese bloque try/catch que detecte el error puede que no esté donde a nosotros nos hubiera gustado que estuviera. Pero esta es otra historia a la que volveré más tarde. Si sabemos dónde se puede producir el error, podemos agregar un punto de interrupción antes del lugar donde ocurrirá (ese lugar seguramente lo habremos descubierto en una ejecución anterior). Podemos agregar un punto de interrupción pulsando la tecla [F9] sobre la línea en la que queremos que se detenga la ejecución del programa. Al llegar a un punto de interrupción, la ejecución del programa se detiene, y podemos inspeccionar los valores de las variables, cambiar dichos valores, ejecutar el código línea a línea (o instrucción a instrucción) y hacer muchas cosas más. Esas “muchas cosas más” son las que en realidad son novedades en la forma de depurar de Visual Studio 2005, ya que en las versiones anteriores también podemos poner puntos de interrupción, inspeccionar las variables, etc. Ahora iremos viendo esas nuevas posibilidades de depuración con más detalle. Sólo mi código Cuando estamos depurando y ejecutando paso a paso la aplicación (ahora veremos cómo), lo lógico es que solo queramos inspeccionar nuestro código, es decir, el código que nosotros hemos escrito. Esto lo haremos marcando la opción “Habilitar Sólo mi código” en las opciones de depuración (“Herramientas” > “Opciones” > “Depuración”, ver figura 2). De esta Figura 1. Opciones de inicio en modo Debug en Visual Studio 2005 <<dotNetManía Puntos de interrupción 44 Cuando estamos en “modo de depuración”, si se produce una excepción (error) en tiempo de ejecución, la ejecución (valga la redundancia) se detiene en el lugar que se produce dicha excepción. Si tenemos un bloque try/catch, dicha ejecución no se detendrá, al menos si forma, el depurador no tendrá en cuenta el código que no esté considerado como “mi código”. Según la documentación de Visual Studio, éste es el proceso que se sigue para determinar qué se considera como “mi código” (transcribo literalmente): En una versión de depuración estándar, se desactiva la optimización y se crean símbolos de depuración para todos los módulos. Cuando se ejecuta una versión de depu- << dnm.inicio Figura 2. Opciones de depuración: “Habilitar Sólo mi código” Aunque esto no es totalmente cierto, al menos si lo tomamos al pie de la letra; ya que podemos añadir un proyecto a nuestra solución, indicar que no se generen los símbolos de depuración (normalmente creando el fichero con la extensión .pdb) e incluso generarlo en modo optimizado y aún así se considera que es parte de “mi código”. Bueno, en realidad no se considera como “nuestro”, pero el IDE de Visual Studio nos advierte de que si realmente no queremos que sea nuestro, pues... que lo indiquemos, tal como vemos en la figura 3. El aviso mostrado en la figura 3 nos indica que en nuestro proyecto tenemos código que no está marcado para depurar o que está marcado para ser optimizado, pero en realidad ese aviso solo se mostrará si no generamos los símbolos de depuración. La selección de la casilla de optimización no afecta y no será causante de que se muestre ese mensaje. ración, se considera que esos módulos pertenecen a “mi código”. Si se llama a una función de biblioteca que se optimiza y no tiene símbolos de depuración, se considera que no es “mi código”. “Solo mi Figura 3. Advertencia de que si queremos hacer ciertas cosas, código” le impide detenerse en que lo indiquemos decuadamente el código de biblioteca, opción que puede desear en la mayoría de los casos. ¿Cómo configurar el proyecto para generar o no los símAhora veremos qué significa esto y cómo podebolos de depuración? mos definir parte de “nuestro código” como si no fuera “mi código” con idea de no detenernos en él cuanSi no queremos generar el fichero con la extendo estemos depurando. sión .pdb, que es el causante de que se pueda depurar Como veremos, (y tal como nos indica la ayuda el código, tendremos que indicarlo en las opciones de Visual Studio), tener habilitada la opción de “Solo avanzadas de generación del código. Según trabajemi código” nos permite centrarnos en el código que mos con Visual Basic o con C#, el nombre de esa nosotros hemos escrito y que es el que en realidad nos interesa depurar. También nos ahorraremos mensajes extras del entorno de desarrollo cuando lo que se va a ejecutar está en librerías externas o en librerías que no están generadas con la opción de depuración. Como hemos visto en la sección anterior, podemos indicar al depurador de Visual Studio que solo ejecute el código considerado como “nuestro”. ¿Qué se considera como código nuestro? Tal como nos indica la documentación de Visual Studio, cualquier código que tengamos referenciado en nuestro proyecto y no tenga símbolos de depuración se considera que no es nuestro; todo lo demás sí se considerará como nuestro código. Figura 4. Opción de generación de símbolos de depuración en C# <<dotNetManía Excluir código para la depuración 45 << dnm.inicio opción será diferente, pero ambas están en el mismo sitio, o casi, al menos si tenemos en cuenta de que en Visual Basic las opciones de generación está en la ficha “Compilar”, mientras que en C#, esa ficha se llama “Generar”. Independientemente de cómo se llamen las opciones o dónde se encuentren, si no queremos que se generen esos ficheros de depuración, lo que tenemos que hacer es indicar el valor none en las opciones de generación. En la figura 4 se muestra esa opción para C# y en la figura 5 para Visual Basic. miento se excluirá. Hay que tener en cuenta que este atributo solo se tendrá en cuenta si hemos seleccionado la opción “Habilitar Sólo mi código”. • DebuggerHidden. Este atributo solo se puede indicar a nivel de procedimiento (ver el comentario anterior para saber qué se considera un procedimiento) y nos servirá para ocultarlo al depurador; de esa forma, no podremos navegar por él en el proceso de depuración, independientemente del valor que hayamos asignado a la opción “Habilitar Sólo mi código”. • Por último, el atributo DebuggerStepThrough impedirá que Visual Studio tenga en cuenta el elemento al que se aplica el atributo (que puede ser una clase o un procedimiento), pero en el sentido de que no podremos ir paso a paso por el código al que está aplicado. A diferencia de DebuggerHidden, podemos poner puntos de interrupción, por ejemplo, en el cuerpo del procedimiento, y en ese caso se detendrá la ejecución al llegar a ese punto de interrupción; pero no nos permitirá la “navegación” paso a paso (ahora veremos cómo podemos ejecutar el código paso a paso). En realidad, ese punto de interrupción solo se tendrá en cuenta si no tenemos habilitada la opción “Habilitar Sólo mi código”. De los tres atributos de ocultación de código al depurador, DebuggerHidden es el único que siempre oculta el código. Figura 5. Opción de generación de símbolos de depuración en C# Indicar partes del código para excluirlo de la depuración <<dotNetManía Si dejamos seleccionada la opción de generación de símbolos de depuración y queremos excluir parte del código del proceso de depuración, podemos usar ciertos atributos definidos en el espacio de nombres System.Diagnostics. Dependiendo de qué comportamiento queramos, podremos usar uno de estos tres atributos: 46 • DebuggerNonUserCode. Este atributo le indica a Visual Studio de que el elemento al que se aplica no se considere como código del usuario, es decir, no se tenga en cuenta como “mi código”. Si el atributo lo aplicamos a una clase, la clase completa se excluirá del proceso de depuración. Si lo aplicamos a un procedimiento (método, constructor, etc.), solo ese procedi- De los tres atributos de ocultación de código al depurador, DebuggerHidden es el único que siempre oculta el código Ejecución paso a paso Cuando estamos depurando una aplicación, usaremos los puntos de interrupción para que la ejecución se detenga al llegar a ellos. Una vez que hayamos detenido la ejecución del programa, podremos ir navegando línea a línea o procedimiento a procedimiento, esto es lo que se conoce como ejecución paso a paso. << dnm.inicio [ Cambiar las combinaciones de tecla Tal como he comentado en la nota, las teclas usadas para ejecutar en modo depuración son las predeterminadas de cada configuración de Visual Studio. De todas formas, si preferimos usar otras combinaciones de teclas, siempre podremos modificarlas y elegir las que más nos gusten. Esto lo haremos cambiando las combinaciones de las teclas desde las opciones de configuración de Visual Studio. Si la tecla elegida ya está asignada a otra opción, el propio entorno nos avisará, tal como vemos en la figura 6. Figura 6. Al elegir una combinación de teclas, si ya se está usando, nos avisará Siguiente instrucción a ejecutar Mientras estamos ejecutando paso a paso, la siguiente instrucción (o línea) a ejecutar estará resaltada en amarillo y con una flecha en la parte izquier- NOTA Las teclas de depuración paso a paso cambian según la configuración de Visual Studio Es importante resaltar que las teclas [F10] y [F11] son las predeterminadas para la configuración del entorno de desarrollo para Visual C#,Visual Web Developer o la conocida como Configuración general de desarrollo. Sin embargo si hemos seleccionado la configuración del entorno de desarrollo para Visual Basic, esas teclas serán [Mayús]+[F8] y [F8], respectivamente. Es importante saber que la configuración del entorno no depende del lenguaje, es decir, si trabajamos con proyectos de Visual Basic y de C# las teclas siempre serán las mismas, ya que es el tipo de configuración elegido el que asignará las teclas de depuración no el lenguaje usado. La tecla [F9] se usa siempre, independientemente de la configuración seleccionada. Como truco, comentar que yo (que normalmente uso Visual Basic para desarrollar) siempre suelo configurar el entorno de trabajo usando la configuración general, de esa forma uso siempre las teclas [F10] y [F11] para navegar por el código. ] <<dotNetManía Cuando seleccionamos la opción “Paso a paso por instrucciones” del menú “Depurar” o usamos la tecla [F11], iremos “navegando” por cada una de las instrucciones del código; si una de esas instrucciones es un procedimiento, entraremos en el procedimiento y podremos ir inspeccionando cada una de las instrucciones que haya. Como ya comenté antes, por procedimiento se entiende cualquier cosa que no sea una clase (o tipo); es decir, una propiedad también es un procedimiento, y por tanto hay veces que se hace tedioso este tipo de navegación por el código, ya que se ejecutarán todas y cada una de las instrucciones que tengamos en “nuestro código”. Si no queremos entrar en los procedimientos, es decir, ejecutarlos, pero no ir paso a paso por cada una de las instrucciones incluidas en él, podemos usar la opción “Paso a paso por procedimientos” o bien usar la tecla [F10]. Si estamos usando esta última forma de navegar por el código, siempre podremos usar la otra opción para entrar en el procedimiento que nos interese. Recordemos los atributos mencionados antes, ya que si hemos usado el atributo DebuggerStepThrough solo podremos detenernos en ese código si hemos puesto un punto de interrupción; y aunque hayamos puesto ese punto de interrupción, una vez en él, no podremos utilizar ninguna de las dos formas de navegar por el código, ya que el IDE se saltará todo el código que haya a continuación (saltar en el sentido de no ir paso a paso), y seguirá por el código en el que hayamos permitido la navegación. 47 << dnm.inicio ción a lo mejor no es tan importante, pero lo de la declaración sí que lo es, ya que no nos dará ningún error de duplicidad de declaración. Esto es bastante útil, ya que nos permite deshacer todo lo que hemos hecho para probar nuevamente a ver por qué ese código no funciona como esperamos. Inspeccionar el contenido de las variables Figura 7. La línea de ejecución actual se resalta en amarillo y los puntos de interrupción en rojo da, tal como vemos en la figura 7. En esa misma figura vemos en rojo los puntos de interrupción. En la figura 7 también podemos apreciar que los dos puntos de interrupción del método Saludo tienen una marca de advertencia y no están en rojo en la barra de la izquierda; esto es así porque ese método está marcado con el atributo DebuggerHidden. La flecha amarilla indica qué es lo que se ejecutará a continuación, es decir, que el código que se resalta aún no se ha ejecutado, y si necesitamos cambiar la localización de la siguiente instrucción a ejecutar, podemos cambiarla moviendo esa flecha a otra posición dentro del código. Por supuesto, no podemos mover ese indicador a cualquier parte, solo donde esté permitido; por ejemplo, si quisiéramos cambiarlo a otro método, no nos lo permitiría: el cursor cambiará a un signo de prohibido, tal como vemos en la figura 8. Mientras estamos en modo depuración, con el código detenido, podemos ver los valores que tienen todas las variables que están en el ámbito actual. Es decir, si estamos en un método, podremos ver qué valores tienen las variables que tengamos declaradas y que estén accesibles en ese punto del programa. Esos valores los podemos ver de dos formas distintas: una de ellas es seleccionando la variable a inspeccionar; si es una variable simple, por ejemplo, una cadena, automáticamente se mostrará una ventana emergente (tooltip) con el valor. Esa ventana permite editar el valor, de forma que podemos cambiarlo in situ. Si la variable a inspeccionar tiene aplicado algún método o propiedad, entonces no veremos el valor; bueno, sí que lo veremos, pero tendremos que ser finos a la hora de posicionar el cursor del ratón en la variable. En cualquier caso, siempre nos quedará la opción de seleccionar la variable al completo para poder mostrar el valor que contiene. <<dotNetManía Figura 8. El indicador de la siguiente instrucción a ejecutar no nos permitirá cambiar de método 48 Cuando cambiamos la siguiente instrucción a ejecutar a una línea anterior a la que se está ejecutando actualmente, todo el código que ya se haya ejecutado se volverá a ejecutar. Esto es lógico, pero si en ese código tenemos declaraciones de variables o instanciamos algún objeto, esas declaraciones volverán a ejecutarse o el objeto volverá a instanciarse. Lo de la instancia- Figura 9. La ventana de inspección de variables << dnm.inicio Por fortuna para los que tenemos poco pulso, están las ventanas de inspección de variables, en las que (tal como podemos apreciar en la figura 9), tenemos dos fichas en las que el propio entorno de desarrollo va agregando las variables que estén actualmente en un ámbito más próximo a la ejecución del programa. En el montaje de la figura 9 vemos esas dos fichas de la ventana de inspección. En la ventana “Automático” se mostrarán las variables que estén más cercanas a la posición de la instrucción que se está ejecutando (habitualmente serán las variables de la línea actual y la anterior), mientras que en la ficha “Variables locales” se mostrarán todas las variables del procedimiento actual. Como vemos en esa figura, se muestran los valores de las variables, además de que en esas ventanas también podemos cambiar los valores de las variables. Si en lugar de inspeccionar una variable simple queremos ver el contenido de un objeto por referencia, por ejemplo, de un array, en ese caso se nos mostrará la información de una forma diferente, ya que el contenido no es un solo valor. En la figura 10 podemos apreciar cómo se muestra el contenido de un array de tipo string; en este caso, podemos acceder a los valores individuales tanto de forma directa como desde la ventana de inspección. Inspección personalizada de variables Como vemos en las figuras 9 y 10, además de las dos ventanas de inspección mencionadas, también podemos utilizar otras con las variables u objetos que Figura 11.Ventana de inspección rápida Conclusiones Con lo explicado en este artículo, tendremos una visión general de parte de lo que la depuración con Visual Studio 2005 (o superior) nos ofrece, aunque aún quedan cosas importantes de las que hablar. Pero eso será en el próximo número de dotNetManía, en el que veremos cómo utilizar todo lo relacionado con editar y continuar y otras cosas relacionadas con la depuración y detección de errores, mientras tanto... ¡que lo depure bien! <<dotNetManía Figura 10. La inspección de los arrays nos permite acceder a los elementos individuales nos interesen. Por ejemplo, si en una variable usamos el método ToString() no se mostrará el valor de forma automática: para ver ese valor tendremos que crear lo que se conoce como una inspección rápida; la forma de hacerlo (además de usando el menú contextual) es seleccionando la variable y pulsando [Mayús]+[F9]. Esa acción hará que se abra un cuadro de diálogo en el que se mostrará el resultado de la llamada a ese método además de permitirnos agregar ese código a una ventana de inspección. En la figura 11 vemos ese cuadro de diálogo y los botones que nos permiten agregar lo que estamos inspeccionando a la ventana de inspección personalizada. También vemos que hay un botón para actualizar el valor; esto es útil si en lugar de mostrar lo que inicialmente habíamos seleccionado queremos cambiar de idea y ver otras propiedades u otros métodos, ya que en esa ventana tendremos acceso a los elementos del objeto que estamos inspeccionando (en este ejemplo es una variable de tipo entero, pero esa variable puede ser cualquiera de las que tengamos definidas en el procedimiento que actualmente se está ejecutando, e incluso de otros procedimientos, al menos si están en ámbito). 49 todonet@qa [email protected] Dino Esposito Dino Esposito es mentor de Solid Quality Learning. Es ponente habitual en los eventos de la industria a nivel mundial.Visite su blog en: http://weblogs. asp.net/despos. (todotNet.QA@ dotnetmania.com) Silverlight. Presente y futuro Demasiadas promesas alrededor de Silverlight 1.0. La comunidad de desarrolladores esperaba mucho de esta versión, pero existen muchas cosas para las que producto no ha sido diseñado y que hoy día no pueden realizarse. Muchas de las expectativas generadas acerca de Silverlight se harán realidad solamente cuando la próxima versión –en preparación para el verano de 2008– esté disponible. En esta columna responderé a preguntas frecuentes sobre Silverlight y su relación con otras tecnologías ricas para aplicaciones Web. Parece que la mayoría de desarrolladores se centra en lo que Silverlight no puede hacer todavía, en lugar de hacerlo en lo que sí puede hacerse con la versión 1.0 ya liberada. Así que mi pregunta es lógica: ¿cuál es el propósito de Silverlight 1.0? Soporta una pequeña porción de WPF y no dispone de utilidades para desarrolladores, tales como controles o librerías de ayuda.Yo incluso me preguntaría si es realmente utilizable… ¿nos puede dar su visión sobre esto? Silverlight 1.0 no es producto para desarrolladores Web. Sí que es, no obstante, un producto que juega un papel estratégico en la lucha y esperamos que derrocamiento del ya vetusto Adobe Flash. Puedes imaginártelo como una cabeza de puente lanzada en el campo de batalla para proporcionar beneficios en un futuro, pero no precisamente en este momento. Más concretamente, la funcionalidad que Silverlight puede ofrecer hoy –versión 1.0, como hemos dicho– se limita a las capacidades multimedia y a mostrar documentos WPF muy simples. El fin último es decirle al mundo que Microsoft ha sacado un anti-Flash, que cuenta, al menos, con algunas pocas ventajas sobre éste. Primero, la descarga de documentos WPF no es una caja negra para buscadores como Google u otros. Segundo, puede reproducir formatos de creación pública, incluyendo WMV, WMA, MP3 y cualquier formato codificado en VC-1, la forma de codificación de la mayoría de las películas en DVD. Y, finalmente, puede programarse utilizando un lenguaje estándar, no propietario, como Javascript. Para reproducir una película desde una página Web, ahora podemos olvidarnos de cualquier reproductor externo (como Media Player) y usar solo Silverlight. Y Silverlight es multiplataforma, soporta varios navegadores y se inserta mediante una etiqueta <OBJECT>. Para preparar un documento Silverlight, no se necesitan obligatoriamente herramientas ad hoc. Todo lo que hay que crear es un fichero XAML, que no es más que un fichero con sintaxis XML. Puedes usar las herramientas de la suite Expression o incluso Visual Studio 2008. Pero en muchos casos sencillos, el Bloc de notas es suficiente. Un fichero XAML describe su salida mediante un subconjunto de elementos de Windows Presentation Foundation. Pero este subconjunto soportado es extremadamente limitado, y no incluye campos de entrada, elementos ubicables, estilos o enlace a datos. Las capacidades limitadas de Silverlight 1.0 se derivan de estas características. Silverlight se presenta en ocasiones, y se percibe a menudo, como la herramienta que hará posible a los desarrolladores construir aplicaciones ricas para Internet (Rich Internet Applications, RIA) que serán distribuidas vía Web, pero con características prácticamente idénticas a las aplicaciones de escritorio Windows. Este es el destino final donde nos exista una versión beta hasta primavera. Esta versión dispondrá de una gran cantidad de potentes características programables para capacitar la creación de una auténtica capa de presentación basada en lenguajes administrados y objetos. Esta es la situación actual. Asumiendo que he comprendido bien el rol y las perspectivas de Silverlight, yo diría que WPF y Silverlight podrían eventualmente convertir las aplicaciones ASP.NET y AJAX en obsoletas. ¿Qué le parece esa predicción? No es algo tan descabellado. Sin embargo, yo creo firmemente que los dos mundos, Windows y Web, van a permanecer separados durante la mayor parte del futuro predecible. Al mismo tiempo, eso sí, la llegada de WPF y Silverlight genera posibilidades de interacción entre la Web y Windows que ahora mismo son impracticables o sencillamente imposibles. Una vez que la próxima versión de Silverlight esté disponible, podrás desarrollar para la Web con la mayoría de las facilidades que tenemos hoy día en el escritorio. Podrías incluso llegar al punto de utilizar el mismo documento WPF para alimentar aplicaciones Web y Windows en un sistema multicapa. Tengamos en cuenta, no obstante, que esto no sucede gratis, pero es un escenario que el uso de patrones de diseño adecuados (p.e., el modelo Vista-Presentador) puede hacer posible. No estoy seguro de que la llegada de Silverlight vaya a revolucionar el mundo del desarrollo Web en la plataforma Microsoft hasta el punto de eliminar a ASP.NET. Como Adobe Flash, se puede usar Silverlight de dos formas: como el entorno o contexto entero de una aplicación Web, o como un reproductor de contenidos especiales en una página ASP.NET estándar. Según mi criterio, es esta segunda opción la que será más ampliamente adoptada. En otras palabras, todavía veo la Web del futuro cercano hecha de páginas HTML con algunas islas WPF en su interior. Silverlight 1.1 (o cual sea su nombre/número final) va a ser una plataforma mucho más potente para la Web. Basado en el conjunto de características conocido hoy, con el añadido de un rico conjunto de etiquetas WPF, Silverlight 1.1 incorporará un CLR muy ligero en el navegador (en modo multiplataforma) para procesar lenguajes administrados (como C#, Visual Basic .NET, Javascript administrado o IronPython), una versión reducida de .NET Framework –que incluirá extensiones LINQ–, manejo de excepciones y clases ad hoc para manejar llamadas remotas a servicios. Al final, WPF y Silverlight forman un poderoso dúo, pero tengo la sensación de que la adopción amplia del producto estará condicionada a las herramientas de programación que los equipos de Microsoft pongan a nuestra disposición. Todavía veo la Web del futuro cercano hecha de páginas HTML con algunas islas WPF en su interior Probablemente, necesitaremos Silverlight para continuar con la exitosa programación basada en ASP.NET con controles de servidor y extensiones del lado del cliente. Si Microsoft puede llegar a ofrecer esto, mi predicción es que la mayoría de los desarrolladores adoptarán Silverlight como una poderosa herramienta para construir aplicaciones Web todavía más potentes. Por otro lado, estamos en esta situación debido a una extraña conjunción astral: casi todos los navegadores soportan un mismo (y potente) conjunto de características programables. Para que WPF y Silverlight destronaran a ASP.NET y AJAX, todos los desarrolladores de todas las plataformas deberían estar de acuerdo. Tecnológicamente hablando, no hay nada que lo impida, pero, en la práctica, yo no apostaría por ello. Aunque sí veo un montón de interacción entre ambos tipos de aplicaciones. <<dotNetManía llevará Silverlight, pero todavía está lejos de donde nos encontramos hoy. La siguiente versión, actualmente etiquetada como Silverlight 1.1 y en fase alfa, probablemente nos lleve donde esperamos. Pero Silverlight 1.1 se espera para después del verano, y probablemente no [email protected] [email protected] << dnm.todonet@qa 51 <<dotNetManía T o d o t N e t . q a @ d o t n e t m a n i a . c o m T o d o t N e t . q a @ d o t n e t m a n i a . c o m << dnm.todonet@qa 52 Intenté insertar un documento XAML en una página ASP.NET y no sucedió nada incluso en máquinas equipadas con la última versión de Silverlight. ¿De qué forma puedo consumir contenido XAML desde una página ASP.NET? Silverlight no es una aplicación preparada para consumir cualquier contenido XAML servido a un navegador. Si apuntas tu navegador a una URL que proporciona un stream XAML, no deberías esperar ningún comportamiento especial en el navegador. La manera de usar Silverlight es ligeramente diferente. Lo primero, inyectas una etiqueta <OBJECT> en una página Web que apunte al motor de Silverlight para la plataforma del navegador. El motor de Silverlight está actualmente disponible para plataformas Mac y Windows y está siendo desarrollado para sistemas Linux por el grupo Mono, en el marco de un proyecto que se conoce como Moonlight. El motor de Silverlight se define en un script llamado Silverlight.js, que debes enlazar a la página. Este fichero es parte del SDK de Silverlight. Contiene objetos de ayuda, que pueden ser instanciados e inicializados para que todo funcione como se espera. En una página Web ASP.NET AJAX, usaríamos el siguiente código: <script type="text/javascript"> function pageLoad() { var parent = $get("host"); createSilverlightHost(parent); } </script> En una página HTML, simplemente ejecutas el código en el manejador del evento onLoad de esa página o puedes situar un bloque <script> dentro de la etiqueta <body>. La función CreateSilverlightHost() es una función definida por el usuario que inicializa la ventana Silverlight. Esta función debe ser vinculada a la página de alguna forma. Normalmente, situamos el cuerpo de la función en un script separado. A continuación inicializamos una ventana Silverlight: function createSilverlightHost(parentElement) { Silverlight.createObject( "xaml/customerview.xaml", parentElement, "SilverlightControl1", { width:'350', height:'120', background:'#111111', version:'1.0' }, { onError:null, onLoad:null }, null); } El parámetro indica el contenedor de la ventana Silverlight, donde el contenido Silverlight será mostrado, en la página. La ventana Silverlight recibe un ID –que es SilverlightControl1 en el código– para poder comunicar con el resto de la página vía Javascript. Finalmente, se definen el tamaño y la apariencia de la ventana. El contenido XAML se identifica mediante una URL. El fichero es descargado y procesado en forma local en el navegador del cliente. Como el XAML se referencia mediante URL, nada impide que una aplicación ASP.NET genere dinámicamente el contenido utilizando un manejador HTTP. ¿Hay algún sitio Web público que utilice Silverlight? Desde luego que sí, ya empiezan a aparecer los primeros sitios que utilizan Silverlight 1.0 para los anuncios o contenidos multimedia1. De todos ellos, me gustaría señalar que http://www.tafiti.com es un ejemplo de sitio potenciado mediante Silverlight. Tafiti semeja el comportamiento de Google y utiliza el motor de Live Search para recoger información a partir de una cadena de consulta. Su interfaz de usuario está enteramente basada en Silverlight, aunque en este momento contiene un montón de código de script. Así que, después de todo, deberías considerar Tafiti como una representación de las funciones que obtienes hoy de Silverlight, pero no todavía del código que escribirás cuando la versión siguiente esté disponible. Traducido al castellano por Marino Posadas 1 Un sitio Web con tales características es http://www.mlb.com. Pero Dino seguramente no es aficionado al béisbol (N. del E. T.) << dnm.laboratorio.net Octavio Hernández Laboratorio.net ILOG Diagrammer for .NET Este mes presentamos ILOG Diagrammer for .NET, un marco de trabajo para la edición y visualización de diagramas y cuadros de mando sacado recientemente al mercado por la multinacional ILOG (http://www.ilog.com), que permite crear sofisticadas y atractivas interfaces visuales para las aplicaciones Windows y Web basadas en .NET Framework. Nombre: ILOG Diagrammer for .NET Versión: 1.0 Fabricante: ILOG Sitio Web: http://www.ilog.com/ Categoría: Componentes de interfaz de usuario Precios: • Licencia de desarrollo: 2.500 EUR. • Licencia de despliegue: contactar con ILOG Octavio Hernández es Development Advisor de Plain Concepts, editor técnico de dotNetManía y tutor de campusMVP. Es MVP de C# desde 2004, MCSD y MCT. ILOG Diagrammer for .NET es un potente conjunto de herramientas, componentes y librerías para el desarrollo de aplicaciones de edición gráfica, visualización, supervisión y monitorización para la plataforma .NET, que simplifican sensiblemente tareas como crear diagramas que permitan establecer o mostrar la relación entre objetos o monitorizar los parámetros de negocios o sistemas dinámicos de la más diversa índole. Las figuras 1 y 2 muestran ejemplos de tales actividades: mientras que en la figura 1 se presenta una aplicación que permite crear y manipular gráficamente diagramas BPM (Business Process Management), en la figura 2 se muestra una aplicación que simula la monitorización en tiempo real del comportamiento del tráfico en túneles subterráneos al estilo de los recientemente inaugurados en Madrid. Estas dos aplicaciones forman parte de los ejemplos que se entregan con el producto. Como complemento de las librerías que componen el SDK de ILOG Diagrammer for .NET, desarrollado al 100% en C#, la instalación del producto integra dentro de Visual Studio 2005 dos nuevos tipos de proyectos, las Aplicaciones ILOG Diagrammer y las Librerías de Símbolos ILOG Diagrammer. Mediante el primer tipo de proyectos es posible crear de una manera visual e interactiva proyectos que incluyan diagramas de los más diversos tipos; al estilo de como hace Visual Studio cuando diseñamos un formulario Windows Forms, en la medida en que vamos arrastrando elementos desde el Cuadro de herramientas hasta el lienzo de diseño el add-in de ILOG Diagrammer va generando el código fuente necesario para reproducir el diagrama en tiempo de ejecución. Durante el diseño de los diagramas, el Cuadro de herramientas de Visual Figura 1. Editor BPM Studio (figura 3) se enriquece con un amplio conjunto de símbolos gráficos pre-programados que están a nuestra disposición desde el primer momento. Estos símbolos no representan otra cosa que clases, por lo que podemos aplicar sobre ellos los patrones familiares de desarrollo basados en el modelo PEM (Propie- <<dotNetManía Ficha técnica 53 << dnm.laboratorio.net Figura 2. Monitor de tráfico en túneles • Modelado de diagramas de clases UML: también se ofrecen controles para representar los elementos y conectores típicos de la notación UML (Unified Modeling Language). • Facilidad de creación de nuevos controles gráficos. ILOG Diagrammer for .NET incluye un amplio conjunto de primitivas (rectángulos, elipses, rutas, líneas, curvas, arcos, textos, imágenes, escalas y otros) y de contenedores comunes (lienzos, paneles apilados o adosados, visores con desplazamiento) que pueden ser utilizados directamente o en combinación con otros gráficos para crear nuevas variaciones. El producto también permite importar gráficos en formato SVG. • Representación avanzada de grafos. El núcleo de la implementación dades-Eventos-Métodos). El resto ya seguramente lo imagina el lector: los símbolos de la librería de ILOG Diagrammer siguen un modelo de arquitectura abierta, y el segundo tipo de proyectos antes mencionado permite precisamente desarrollar nuevas librerías de símbolos para reutilizar en nuestros propios proyectos o distribuir a terceros. Características principales <<dotNetManía A continuación se enumeran las principales características del producto que podrían ser de interés para los lectores: 54 • Amplia gama de controles listos para su uso. El amplio conjunto de controles gráficos incluidos de serie en ILOG Diagrammer for .NET permite satisfacer un amplio rango de necesidades de los diseñadores gráficos en muchos dominios de aplicación diferentes. Estos controles incorporan un conjunto de comportamientos e interacciones predeterminadas; en todos los casos, es posible redefinir las propiedades y métodos virtuales correspondientes para crear nuevas variaciones. Los controles incorporados de serie en ILOG Diagrammer for .NET se orientan a los siguientes tipos de aplicaciones: Figura 3. El Cuadro de herramientas de VS2005 durante la edición de diagramas • Modelado y monitorización de procesos de negocio: se ofrece el conjunto completo de símbolos de la notación BPMN (Business Process Modeling Notation). • Monitorización de negocios: el producto incluye múltiples tipos de controles para el desarrollo de cuadros de mando y paneles de monitorización para negocios, incluyendo barras de progreso, relojes, visores de gráficos comerciales y botones. de ILOG Diagrammer for .NET incluye una implementación eficiente de una estructura de datos para representar grafos, entidades complejas que constan de nodos y enlaces que los interconectan. Esta estructura de datos es ideal para representar redes, procesos, flujos y cualquier tipo de diagramas técnicos o de negocio. Cualquier control gráfico puede servir como nodo de un grafo, y el producto ofrece una amplia variedad << dnm.laboratorio.net Noticias • Infragistics (www.infragistics.com) acaba de sacar al mercado NetAdvantage for .NET volumen 3, una nueva edición de la popular suite de herramientas de interfaz de usuario para Windows y la Web. Entre las novedades más significativas de esta edición están la inclusión de nuevas metáforas de navegación asociadas a la experiencia de usuario de Windows Vista y la adición de nuevas posibilidades de exportación a XPS y PDF para permitir nuevos escenarios de compartición de documentos y generación de informes, en lo que respecta a NetAdvantage for ASP.NET. Asimismo, la empresa ha presentado la CTP (Community Technology Preview) de Aikido, un nuevo marco de trabajo para ASP.NET basado en AJAX. • Iron Speed (www.ironspeed.com) ha puesto a disposición del público Iron Speed Designer v. 5.0, una nueva versión de este potente generador de generación automática de aplicaciones Web, que incorpora una cantidad realmente impresionante de novedades que harán el producto aún más útil y productivo para sus usuarios. • Business Objects (www.businessobjects.com) acaba de anunciar Crystal Reports 2008, nueva versión (la duodécima) de la conocida herramienta de creación y ejecución de informes que permitirá a los usuarios alcanzar una mayor productividad, condensar una mayor cantidad de información en un informe evitando así la proliferación de éstos, aumentar la interactividad de los informes e integrar objetos de Flash, Flex y Xcelsius para producir informes más impactantes. En el marco de esta sección, dotNetManía describirá en próximas ediciones las características principales de estos productos. • De rejilla. Caracterizado por el hecho de que no se dibujan los conectores; puede utilizarse en cualquier caso en que se desee simplemente disponer gráficamente un conjunto de elementos. • Editores personalizables. Entre sus ejemplos, el producto incluye tres editores independientes completos y con código fuente incluido: un editor de diagramas, un editor de diagramas de clases UML y el ya mencionado editor de diagramas BPMN. • Despliegue para el escritorio o para el navegador. Las aplicaciones creadas con ILOG Diagrammer for .NET pueden ser desplegadas como aplicaciones Windows Forms o (con mínimos cambios) como aplicaciones ASP.NET con soporte Ajax (basado en las extensiones de Microsoft e independientes de Figura 4. Editor de diagramas UML como otro proveedor específiaplicación Web. co). Este nivel de flexibilidad es especialmente útil si una misma aplicación debe ejecutarse en diferentes plataformas. La figura 4 muestra al editor de diagramas de clases UML ejecutándose como una aplicación Web. Conclusión En este artículo hemos descrito las principales posibilidades que ofrece ILOG Diagrammer for .NET, un potente marco de trabajo en código manejado para el desarrollo de interfaces gráficas interactivas para Windows y la Web. El alto precio de salida del producto está sin duda más que justificado por la calidad y las prestaciones que ofrece; invito al lector a descargar la versión de evaluación [1] y comprobarlas por sí mismo. Referencias [ 1] Sitio Web del producto: http://www.ilog.com/products/ diagrammernet. <<dotNetManía de tipos de conectores: rectos, curvilíneos, ortogonales, etc. para enlazar los nodos entre sí. Adicionalmente, el producto incluye toda una serie de servicios avanzados como la detección de intersecciones entre conectores o la interconexión entre diferentes grafos. • Distribución automática de grafos. ILOG Diagrammer for .NET ofrece un conjunto sofisticado de algoritmos para la distribución automática de los nodos y los conectores, que a la vez que intentan satisfacer objetivos generales como la minimización del área de dibujo necesaria, la minimización de la cantidad de intersecciones entre conectores, entre otros, permiten al usuario de una manera rápida distribuir los nodos del grafo en dependencia del tipo de diagrama que desea crear. Entre los algoritmos de distribución disponibles están: • Jerárquico. Generalmente utilizado en aplicaciones de ingeniería eléctrica (diagramas de circuitos), ingeniería industrial (diagramas de procesos), gestión de software (diagramas UML, diagramas de flujo). • Arbóreo. Ideal para la representación de diagramas organizativos, diagramas de bases de datos o mapas de sitios Web. • Guiado por fuerza (force directed). Utilizado en diagramas de redes de telecomunicaciones o redes semánticas, entre otras aplicaciones. 55 comunidad.net European Silverlight Challenge El concurso de desarrollo de Silverlight se ha ampliado a toda Europa, aumentando también los premios. INETA Europa (http://europe.ineta.org), en colaboración con Microsoft, ha preparado esta competición que ya ha empezado y que finalizará el día 31 de enero de 2008. La competición se realizará en dos fases: 1. Competiciones Nacionales. Estas se realizarán de forma local en cada país bajo la supervisión y apoyo del equipo de INETA. 2. Competición Europea (Gran Final). En ella participarán solo los participantes que hayan obtenido el primer premio con su aplicación ganadora. Si crees en tu talento, apúntate y participa en la competición “European Silverlight Challenge” y gana, además del reconocimiento de la comunidad, fabulosos premios por un valor total de 160.000€ (según precio de mercado), incluyendo tickets para el MIX 2008 (con viaje y estancia incluidos), suscripciones MSDN, etc. El objetivo de la competición es desarrollar una aplicación, módulo o componente .NET en la que su interfaz de usuario esté desarrollada con la tecnología Silverlight. Esta participación deberá acatar la licencia MS-PL para poder ser distribuida y utilizada gratuitamente por grupos de usuarios de INETA o de cualquier otra comunidad en sus sitios Web y comunidades técnicas online. Más información en http://silverlightchallenge.eu. Para participar en la competición española: http://desafiosilverlight.bcndev.net. 3º Aniversario GUSE.NET Durante los días 23, 24 y 25 de noviembre se celebró el III Aniversario de Gusenet, en Santa Pola (Alicante). Como ya viene siendo habitual en este evento, intentamos combinar las sesiones técnicas con un poquito de ocio que además pueda ser compartido por nuestras parejas, con el objetivo de pasar un fin de semana completo, con diversas cenas, comidas, visitas organizadas por la ciudad, etc. Tuvimos una agenda interesante, en la que pudimos contar con excelentes ponentes, y compuesta por dos sesiones sobre novedades que vamos a encontrar en Visual Studio 2008 y una mesa redonda sobre el pasado, presente y futuro del grupo, con aportaciones interesantes que empezaremos a poner en práctica en próximos eventos. Centrándonos en las sesiones técnicas, comenzamos con una charla de nuestro amigo “Guille”, que nos habló de las novedades de VB9, consiguiendo, además de transmitir de forma muy clara dichas novedades, hacer una sesión muy amena, cargada de bromas y risas. Y cómo no, aprovechó para vender algún libro, camisetas cuyo importe será donado a DotNetSolidario, y hacer algunos regalos. A continuación pudimos contar con David Salgado, de Microsoft Ibérica, quien nos habló principalmente de AJAX, haciendo una sesión muy interesante y participativa, donde invitó al público a hacerle todo tipo de preguntas, incluidas aquellas que no iban directamente relacionadas con el tema en cuestión, consiguiendo así una excelente comunicación con el público, que pudo resolver cualquier duda que planteó. CSLA.NET: introducción al framework de desarrollo CSLA.NET 3.0 El pasado 21 de noviembre tuvimos la enorme fortuna de poder contar con la presencia de uno de los grandes del mundo .NET, Rockford Lhotka, que aprovechando una estancia en Barcelona nos ha honrado con una charla en la que pudimos ver la nueva arquitectura CSLA 3.5 (en desarrollo actualmente), con lo que fuimos honrados doblemente: con el gran speaker que es (además de un gran escritor y arquitecto de software), así como con la posibilidad de echar un vistazo al nuevo CSLA 3.5. La sesión transcurrió sin problemas, totalmente en inglés y con asistencia de público internacional vía Live Meeting. Por último, se regalaron dos de los últimos libros sobre CSLA por parte de Lhotka al público, todo un detalle por su parte. La sesión de firma de libros destapó más de un fan de Lhotka oculto entre el público. La experiencia se podría calificar de genial. Además de que desde los inicios de la vida de BcnDev, sobre principios del 2006, teníamos muchas ganas de realizar una sesión sobre CSLA, al final la ha realizado el mismísimo Lhotka. Si tenéis la oportunidad de asistir a alguna sesión suya, online o presencial, recomendamos altamente la asistencia. Yo, Robot Si desarrollas con tecnología Microsoft, debes saber que no solo puedes crear aplicaciones comerciales con Visual Studio, también puedes divertirte y mucho. En esta charla veremos algunas aplicaciones de Microsoft Robotics Studio y LEGO Mindstorm, cómo trabajar con Visual Studio .NET y un WiiMote, cómo controlar un helicóptero utilizando Visual Studio y alguna sorpresita más. El viernes 14 de diciembre tendrá lugar en el salón de actos del Hospital Juan Ramón Jiménez de Huelva el evento "Yo, Robot". Registro: http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032358807&Culture=es-ES. Como siempre, después del evento colgaremos los materiales disponibles en nuestra sección de eventos (http://www.onobanet.com/eventos/eventos.aspx). biblioteca.net Microsoft Expression Web Plain & Simple Katherine Murray Editorial: Microsoft Press Páginas: 256 Publicado: octubre de 2007 ISBN: 978-0735625198 Idioma: inglés Estamos trabajando con Expression Web desde su aparición, y la impresión es positiva, así que una obra sobre este tema (una de las primeras) merece la pena citarse, especialmente cuando viene directamente “de la casa”. Es una obra cortita, que se lee –casi- del tirón, y decimos casi, porque merece la pena perderse un poco en algunos de los ejercicios prácticos que presenta, para adquirir soltura con un producto que, una vez controlado, puede ser muy productivo. Que nadie espere análisis en profundidad, pero es una obra idónea para los que se están iniciando con las capacidades de la herramienta (que son bastantes). Cubre todas las tareas fundamentales para la creación de sitios profesionales y se deja ver la experiencia de la autora (a más de la de usuario): tiene más de 40 libros publicados. Su lectura resulta didáctica y divertida. C# 3.0 y LINQ Octavio Hernández Leal Editorial: Krasis Press Páginas: 290 Publicado: noviembre de 2007 ISBN: 978-8493548919 Idioma: castellano novedades Es un placer comentar esta obra por varias razones (algunas personales): es una de las primeras en su género que se publican en castellano; algunas partes de su contenido las habrá podido leer el lector en esta revista; y –además– se trata del Editor Técnico de dotNetManía. Una obra corta, pero, a diferencia de la anterior, intensa. Hay que decir también que, debido al formato de publicación que utiliza Krasis –con muy cuidada encuadernación en cartoné–, las casi 300 páginas del libro dan para bastante más de lo que se podría adivinar detrás de esa cifra. Octavio Hernández repasa en los primeros cuatro capítulos las novedades aportadas por el lenguaje a partir de la versión 2.0 (especialmente los tipos genéricos), para pasar, a continuación, a abordar los fundamentos de LINQ y su reflejo en el lenguaje C# 3.0 y su librería básica de apoyo (LINQ to Objects). La última parte del libro describe las posibilidades que ofrecen los principales proveedores de LINQ contenidos en .NET 3.5, junto a abundantes ejemplos, probados hasta la última coma (perdón, punto y coma). Introducing Microsoft Expression Design Greg Holden. Editorial: Course Technology PTR. Páginas: 600. Disponible: enero de 2008. ISBN: 978-1598631562. Idioma: inglés. Microsoft Expression Blend Unleashed Brennon Williams. Editorial: SAMS. Páginas: 500. Disponible: junio de 2008. ISBN: 9780672329319. Idioma: inglés. TEXTO: MARINO POSADAS desván Marino Posadas <<dotNetManía El ADN como lenguaje de programación 58 Se había intentado antes, pero el proyecto de investigación dirigido por Erik Winfree, profesor de ciencias de la computación en el Instituto de Tecnología de California, puede considerarse el primer intento serio de reunir bioquímica e informática. “Podemos diseñar una serie de estructuras capaces de crear patrones complejos, circuitos, y motores”, afirmó respecto a las pruebas obtenidas creando patrones y estructuras de ADN en tubos de ensayo, Winfree, quien además se define como un ferviente creyente de que la anunciada (pero todavía no producida) comunión entre las dos disciplinas científicas está a punto de producirse, añadía: “No se trata de quedarnos en el mero ensamblado de formas geométricas utilizando ADN. Si entendemos el lenguaje, podríamos diseñar respuestas biológicas a través de la re-programación, para terminar con virus reales”. De cualquier forma, Winfree no es el único que investiga seriamente con esta posibilidad. Hace ya algún tiempo, la doctora Lila Kari de la University of Western Ontario (Canada), especializada en lenguajes formales, ganó el premio Florence Bucke por sus trabajos de recombinación genética del ADN, en los que demostraba que, teóricamente, se podría utilizar este tipo de combinación para simular cualquier operación de las realizadas habitualmente por un ordenador. La forma de plantear los problemas sería lo más complejo y duradero, mientras que el tiempo de cálculo se reduciría de forma tan drástica, que proposiciones que ahora escapan al cálculo de la mayoría de los ordenadores (o sea, que tardarían años en realizarse) podrían resolverse en cuestión de horas. Y es que las conexiones entre bioquímica e informática son cada vez más numerosas. Lo último en conexiones directas lo presentaba hace poco un grupo de científicos de la Universidad de Arizona, dirigidos por Charles M. Higgins, quienes han construido un robot cuyo movimiento está vinculado al cerebro de una polilla (como lo oyen). El dispositivo (ver foto adjunta) conecta el cerebro de la polilla (inmovilizada en un tubo de ensayo especial, y rodeada de dibujos que –al moverse– le sugieren movimiento) con el robot, y cuando el escenario de control genera la sensación de movimiento el robot responde de varias formas. Higgins afirma haber construido el dispositivo como medio de estudio neuronal, pero otros colegas afirman que podría utilizarse en sentido inverso; esto es, sugiriendo reacciones en el cerebro mediante movimientos robotizados. Para más información sobre este último experimento, ver el artículo de Physics.org: http://www.physorg.com/news114715561.html. noticias.noticias.noticias documentos en la red ¿Utiliza Captchas como Webmaster? Si cree que son seguros, no se pierda este artículo sobre las vulnerabilidades de estos gráficos que supuestamente permiten diferenciar la percepción humana de las acciones de los bots en la red. En el artículo Has CAPTCHA Been "Broken"? (http://www.codinghorror.com/blog/archives/001001.html), Jeff Atwood (Coding Horror) analiza las vulnerabilidades de estos mecanismos e incluso indica la página Web de un hacker chino que consigue romper la mayoría de ellos. ¡SQL Server 2008 podrá ser administrado mediante PowerShell! Jeffrey Snover (Microsoft) anunciaba recientemente en el blog del equipo de desarrollo de Windows PowerShell esta noticia que –sin duda– merece la pena leer tanto si se está en el mundo de IT, como en el de desarrollo o se es un DBA. Para más datos, visitar: http://blogs.msdn.com/powershell/archive/2007/11/13/ sql-server-support-for-powershell.aspx. sitios del mes La propia MSDN recoge la actividad de los bloggers más destacados (no conocemos el criterio que siguen), y los agrupa en páginas para los interesados en un lenguaje o tecnología determinados. Este es el caso de Visual Basic Blogs (http://msdn2.microsoft.com/ en-us/vbasic/ms789067.aspx#mvp) donde aparecen algunos de los autores habituales de esta revista. utilidades del mes Recover Keys. Una más que útil herramienta ahora que todos los programas tienen claves, y no siempre hemos prestado atención a dónde las guardábamos. Es capaz de recuperar claves de más de 140 productos. Una tranquilidad y solo un 1 Mb de descarga (el programa costará 20$ en el futuro, pero es gratuito en la actualidad por tiempo limitado, otra razón para descargarlo pronto…) El sitio: http://www.giveawayoftheday.com/recover-keys. bCheck: un sitio de utilidades. Se trata de pequeñas utilidades –algunas no ocupan más de 12K–, pero son gratuitas y algunas pueden resultar extremadamente útiles. Como HoeKey, que permite configurar el teclado como se quiera (cualquier combinación, cualquier programa), o Capster, que ejecuta cualquier programa al inicio de Windows solo si la tecla de control está pulsada, o Reso, que lanza una aplicación en la resolución favorita del usuario devolviendo el sistema al estado en que se encontraba al salir de ésta. Por cierto, si alguna vez podemos decir de un sitio que es minimalista al máximo, es éste: http://www.bcheck.net.