Rendimiento del WPF Designer en Visual Studio 2010

El otro día hablando con Jesús Jimenez, le comentaba que el rendimiento de Visual Studio 2010 era bastante malo. En cambio, él me comentaba que más o menos podía trabajar bien con la herramienta. Que no es lo mismo que 2008, en cuanto a rendimiento, pero se puede hacer vida de él. Él está desarrollando con MVC 2, en cambio, yo estoy utilizando WPF.

Trabajando con WPF el rendimiento del designer es muy malo, hasta el punto de conseguir bloquear por completo el Visual Studio 2010. Si el designer se encuentra algún error dentro del XAML, adiós Visual Studio.

En el blog de bharry leyendo uno de sus post dice “the WPF designer performance in Beta 2 was unacceptable”. También en el post, “Some WPF Designer Performance Improvements”, explica cómo mejorar un poco el redimiendo del mismo. Además yo añadiría la posibilidad de hacer que el Visual Studio 2010 abra la vista de XAML por defecto, en vez de abrir la del designer. En mi caso me ha ofrecido buenos resultados y se puede hacer vida de la herramienta.

Para activar la opción  “Always open documents in full XAML view”, ir  a Tools -> Options -> Text Editor -> XAML -> Miscellaneous.

SplashScreen en Silverlight

Cuando una aplicación o componente Silverlight es cargado aparece un icono indicando que el plugin se está cargando. Existe un diseño por defecto. Este Sphlas Screen puede modificarse por uno de diseño propio. Lo único que hay que tener en cuenta es que sólo se pueden utilizar controles de Silverlight 1.0.

Para crear un nuevo SplashScreen hay que añadir al proyecto web un nuevo elemento del tipo Silverlight JScript Page. Esto añade al proyecto dos archivos: uno archivo .xaml y otro .js. Dentro del .xaml irá el diseño de la pantalla y en el .js su funcionalidad.

Dentro de la definición del control de Silverlight se le puede indicar que utilice la nueva página como Splash Screen. Para ello se hace uso de la propiedad SplashScreenSource.

<asp:Silverlight runat="server"
    Source="~/ClientBin/Client.xap" 
    MinimumVersion="3.0.40624.0" 
    SplashScreenSource="~/SplashScreen.xaml" />

Para conseguir centrar nuestro diseño dentro de la ventana, lo más sencillo es utilizar un elemento Grid, con el tamaño a Auto. Este elemento por si sólo centrará cualquier elemento hijo.

<Grid xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
      xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
      Background=Black>
</
Grid>

Para suscribirse al evento que indica el porcentaje cargado hay que definir un método dentro del archivo .js. Este método actuará de handler para el evento OnSourceDownloadProgressChanged.

function onSourceDownloadProgressChanged(sender, eventArgs){
 sender.findName("progressBar").Width = 
   eventArgs.progress * sender.findName("progressBarBackground").Width;
}

Para asociar el método se debe de utilizar la propiedad OnSourceDownloadProgressChanged.

<param name="onSourceDownloadProgressChanged" 
    value="onSourceDownloadProgressChanged" />

Un diseño completo como ejemplo podría ser:

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      Background="Black">
  <StackPanel>
    <TextBlock Text="Sector7G" 
               FontSize="14" 
               Foreground="#FFFFFFFF" 
               HorizontalAlignment="Center" 
               FontFamily="Segoe UI" 
               FontWeight="Bold"/>
    <Border x:Name="progressBarBackground" 
            HorizontalAlignment="Center" 
            VerticalAlignment="Center" 
            BorderBrush="#FFB6D5EC" 
            BorderThickness="1" 
            Height="14" 
            Width="200">
      <Rectangle x:Name="progressBar" 
                 Width="0" 
                 Height="14" 
                 HorizontalAlignment="Left" 
                 Margin="1" 
                 VerticalAlignment="Bottom">
        <Rectangle.Fill>
          <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
            <GradientStop Color="#FF6DAAD9" Offset="0.548"/>
            <GradientStop Color="#FF496272" Offset="0.961"/>
          </LinearGradientBrush>
        </Rectangle.Fill>
      </Rectangle>
    </Border>
  </StackPanel>
</Grid>

TextTrimming

Hoy he leído que Silverlight 4 ya incluirá un control que TextTrimming. Este control es capaz de ajustar un texto al tamaño de un TextBlock y cortarlo concatenándole “…” en caso de que sea demasiado largo y no entre dentro del TextBlock.

“Sertor7G es un blog sobre…”

El otro día tuve que implementar esta funcionalidad en una de las aplicación que estoy desarrollando sobre Silverlight 3. Después de buscar en google, encontré un post donde exponían el código fuente de un control que se habían hecho a mano. Dejo la dirección del blog por si a alguien le resulta de utilidad TextTrimming TextBlock for Silverlight . Dentro del código fuente describen los términos de licencia de su uso.

Migración de Silverilght 2 a Silverlight 3

Ahora que ha salido Silverilght 3 seguramente se empiecen a migrar muchos proyectos hechos con Silverlight 2 a esta nueva versión. No es que sea estrictamente necesario, ya que con el plug-in de Silverlight 3 se pueden ejecutar ambas versiones. Aunque si se quieren aprovechar las novedades de Silverlight 3 es algo recomendable migrar. Además el proceso de migración es bastante sencillo, como se describe a continuación.

Paso 1: El primer paso es erradicar de la máquina cualquier vestigio de Silverlight 2. Así que hay que desinstalar: Silverlight 2 SDK, Silverlight 2.0 tools for VS2008 SP1 y Silverlight. Si el equipo tiene instalado el toolkit de controles para Siverlight 2, también es necesario desinstalarlo.

Paso 2: El siguiente paso es instalar Silverlight 3. Hay que instalar todas las herramientas: Silverlight 3 Tools for Visual Studio 2008 SP1 y Silverlight 3. Opcionalmente se puede instalar el Silverlight Toolkit.

Nota: Silverlight 3.0 tools for VS2008 SP1 instala el SDK también.

Paso 3: Una vez instalado Silverlight 3 hay que abrir la solución del proyecto a migrar. Al abrirla Visual Studio lanzará un Wizard. Este Wizard se encarga de realizar la migración de los proyecto.

Paso 4: Hay que cambiar la versión de Silverlight utilizada en nuestra página. Así que hay que cambiar el valor de la propiedad MinimumVersion de 2.0.31005.0 a 3.0.40624.0.

Paso 5: Cambiar de referencias de controles y librerías. Por ejemplo en el caso del control AutoCompleteBox, ya no se encuentra en el control toolkil. Si no que el control AutoCompleteBox ha sido absorbido por la librería de controles propia de Silverlight.

El proceso de migración es bastante sencillo. Si la aplicación es de un tamaño mediano / grande y se han utilizado controles del control toolkit, probablemente de bastante guerra hacer que compile.

Error En Excel: Old Format Or Invalid Type Library

Trabajando con Excel puede que te hayas encontrado con este mensaje de error.

Error: Old format or invalid type library. (Exception from HRESULT: 0x80028018 (TYPE_E_INVDATAREAD))

Este error se produce cuando la versión del Excel instalada en el equipo se encuentra en inglés y el sistema operativo en español.

Para solucionar el problema basta con cambiar la cultura del thread de ejecución. Debe de estar en inglés.

Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");

Review: No Me Hagas Pensar

Título: NO ME HAGAS PENSAR. Una aproximación a la usabilidad en la web
Autor: Steve Krug
Nº Páginas: 216

“No me hagas pensar” se trata de un libro sobre usabilidad en el entorno web. El libro intenta dar una serie de consejos y enseñadas sobre el diseño web. Con el objetivo de facilitar el uso de la web a los usuarios. El reto es no hacerles pensar, es decir, que sea lo más sencillo posible para ellos navegar por una web.

El autor, Steve Krung, presenta su experiencia en este campo. Trata los conceptos de usabilidad de una manera muy clara, sencilla y amena. Además de ilustrar en todo momento, con ejemplos de web reales, sus ideas. También en varios capítulos, al final, presenta una serie de ejercicios utilizando webs de ejemplos.

Entre otros temas habla sobre: cómo debe de ser la jerarquía de títulos dentro de la web; Cómo han de colocarse las “migas” para que el usuario sepa en todo momento donde se encuentra; Cómo colocar la información dentro de la web para que no resulte confusa al usuario; Cómo realizar pruebas de usabilidad para que estas resulten útiles; etc…

Resumiendo un poco el libro. El autor viene a decir que de un solo vistazo, el usuario debe de saber: donde se encuentra dentro de la web y de que trata la web. Sobre esto esto habla a lo largo de los capítulos del libro:

  • Prólogo.
  • Introducción.
  • Capítulo 1. ¡No me hagas pensar!.
  • Capítulo2. ¿Cómo usamos realmente la web?.
  • Capítulo 3. Diseño de rótulos 101.
  • Capítulo 4. ¿Animal, vegetal o mineral?.
  • Capítulo 5. Omisión de palabras innecesarias.
  • Capítulo 6. Señales en la calle y migas.
  • Capítulo 7. El primer paso para la recuperación es admitir que ha perdido el control de la página principal.
  • Capítulo 8. El granjero y el ganadero deben ser amigos.
  • Capítulo 9. Prueba la usabilidad por 10 centavos el día.
  • Capítulo 10. La usabilidad como cortesía común.
  • Capítulo 11. Accesibilidad, hojas de estilo en cascada y usted.
  • Capítulo 12 ¡Ayuda! Mi jefe quiere…. Lecturas recomendadas.

Además al final del libro el autor recomienda una serie de lecturas:

Una lectura muy recomendable, no todo va a ser código.

Detección de Colisiones de Objetos 3D en WPF

Window Presentation Foundation proporciona la posibilidad de trabajar con objetos 3D dentro de una aplicación. Ello hace que se puedan desarrollar aplicaciones muy ricas utilizando modelos en 3D.

Si la aplicación trabaja con objetos 3D que dan la posibilidad de desplazarse a lo largo de la pantalla puede ser interesante detectar colisiones entre ellos. A la hora de detectar colisiones entre objetos en una aplicación podemos optar por varias estrategias. Por ejemplo, dentro de XNA podemos encontrar: bounding box, bounding sphere y bounding frustrum. El Framework de XNA ya proporciona métodos para facilitar las colisiones entre los objetos.

  • Bounding box: Esta técnica se utiliza cuando el objeto se adapta a una forma rectangular. Lo que hace es envolver el modelo en una caja. Si el modelo no es totalmente rectangular puede que se den falsas colisiones.
  • bounding sphere: Es técnica envuelve el objeto con una esfera. Se utiliza cuando el modelo se adapta mejor a la forma de una esfera.
  • bounding frustrum: Esta técnica no es usada realmente para controlar las colisiones. Ya que controla el espació visto por la cámara. Así puede determinar si lo que se está viendo es un objeto o no y por consiguiente decidir si dibujarlo o no.

La técnica más sencilla de desarrollar con WPF es la de bounding box. El Framework proporciona los métodos necesarios para ello.

Dentro de un GeometryModel3D podemos encontrar la propiedad Bound. Esta propiedad devuelve un objeto del tipo Rect3D. Este objeto representa el rectángulo que envuelve al modelo. Además la propia clase Rect3D cuenta con un método, IntersectsWith. Este método recibe como parámetros otro objeto Rect3D y verifica si entre ambos rectángulos hay una intersección. Si hay una intersección, devuelve True. Eso quiere decir que los objetos están colisionando.

Rect3D rectModel1 = ((GeometryModel3D)mv3D.Content).Bounds;
Rect3D rectModel2 = ((GeometryModel3D)mv3D.Content).Bounds;

if (rectModel1.IntersectsWith(rectModel2))
{
    //Se ha producido una colisión.
}
else
{
    //No hay colision entre ambos modelos.
}

Si sobre el modelo se ha hecho alguna transformación, habrá que tenerlo en cuenta a la hora de obtener el rectángulo que envuelve al modelo. De tal manera, que también esa transformación deberá ser aplicada al Rect3D resultante. Para ello existe el método TransformBounds que aplica las transformaciones a un Rect3D.

 

ModelVisual3D mv3D = new ModelVisual3D();
ModelVisual3D mv3D2 = new ModelVisual3D();

mv3D.Content.Transform = new ScaleTransform3D(0.2, 0.2, 0.2);
mv3D2.Content.Transform = new ScaleTransform3D(0.2, 0.2, 0.2);

Rect3D rectModel1 = mv3D.Transform.TransformBounds(mv3D.Content.Bounds);
Rect3D rectModel2 = mv3D2.Transform.TransformBounds(mv3D2.Content.Bounds);

if (rectModel1.IntersectsWith(rectModel2))
{
    //Se ha producido una colisión.
}
else
{
    //No hay colision entre ambos modelos.
}

Review: Scrum y XP desde las Trincheras

Título: Scrum and XP from the Trenches
Autor: Henrik Kniberg
Nº Páginas: 140

En Scrum and XP from the Trenches su autor Henrik Kniberg habla sobre su experiencia con estas metodologías. Cuenta como ha aplicado y combinado estas dos metodologías los equipos de desarrollo de su empresa. Esto hace que se trate de un libro muy práctico, ameno y de fácil lectura.

Henrik no profundiza mucho en los conceptos, pero sí que hace una descripción breve sobre ellos. Se centra más en explicar cómo ha aplicado las diferentes herramientas de Scrum y cuáles han sido sus conclusiones después de ver cómo funcionaban. Además habla de cómo ha combinado Scrum con XP y de los resultados obtenidos de ello.

Lo interesante de este libro es justo el enfoque dado por el autor. Ver Scrum desde la práctica y la experiencia y no solamente desde el papel y la teoría.

A lo largo del libro, Henrik habla de cómo realizar las pilas de producto, de cómo planificar los Sprints, cómo hacer retrospectivas del sprint, de cómo hacer pruebas, etc.… Concretamente el índice es el siguiente:

 

  1. Introducción
  2. Cómo hacemos pilas de producto
  3. Cómo nos preparamos para la planificación de Sprint
  4. Cómo hacemos la planificación de Sprint
  5. Cómo comunicamos los Sprints
  6. Cómo hacemos pilas de Sprint
  7. Cómo distribuimos la sala del equipo
  8. Cómo hacemos Scrum diarios
  9. Cómo hacemos la demo de sprint
  10. Cómo hacemos retrospectivas de sprint
  11. Descansos entre Sprints
  12. Cómo combinamos Scrum con XP
  13. Cómo hacemos pruebas
  14. Cómo manejar múltiples equipos Scrum
  15. Cómo gestionamos equipos distribuidos geográficamente
  16. Lista de comprobación del Scrum Master

Además al final de libro, el propio autor recomienda una serie de lecturas bastante interesantes sobre el tema:

El libro lo podréis contra en varios idiomas, también en español, aunque personalmente os recomiendo la versión en inglés.

Localización de una Aplicación Basada en PRISM

Es difícil localizar una aplicación WPF con las herramientas proporcionadas en el .Net Framework 3.5. El proceso para realizarlo sería el siguiente:

  • Generar un diccionario de recursos.

  • Enlazar el diccionario a la aplicación en el App.xaml.

  • Ejecutar el MSBuild script para generar un Id único para cada control localizable en la aplicación.

  • Ejecutar la herramienta LocBaml (incluida en el SDK) para extraer todos los Aid en un archivo separado por comas.

  • Copiar el archivo generado por LocBaml a una carpeta (una para cada lenguaje).

  • Volver a ejecutar la herramienta LocBaml para importas todas las entradas dentro del diccionario.

  • Compilar.

Esta forma de hacerlo tiene algunos problemas:

  • Sólo puedes tener un archivo de diccionario de recursos por aplicación. Cada módulo no podrá tener el suyo propio.

  • El proceso es difícil y propenso a los errores. Lo que hace que sea costoso de mantener.

  • No puedes cambiar el lenguaje de la aplicación en tiempo de ejecución. Es necesario reiniciar la aplicación para poder reflejar el cambio de idioma.

Para arquitecturas como PRISM (Composite Application Guidance for WPF), que se basan en módulos, es muy importante que cada módulo pueda tener sus propios archivos de recursos. Puede que estos módulos sean desarrollados por separado y equipos diferentes. Además es interesante que el proceso de localización sea sencillo y fácilmente mantenible. Normalmente los textos de las traducciones suelen cambiar bastante.

Para solucionar esto, y solventar todos los problemas existe WPFLocalizeExtension. Se trata de un framework open source. Este framework ha sido modificado para soportar localización de assemblies (plug-in) cargados dinámicamente.

Este framework se basa en archivos de recursos lo que hace que sea bastante sencillo mantener las traducciones de los diferentes idiomas. Así que cada módulo puede tener su propio archivo de recursos con sus traducciones. Además, permite cambios de idioma en caliente.

Ahora el proceso de localización es más sencillo:

  • Modificar el archivo de proyecto .csproj añadiendo <UICulture>en-US</UICulture> en el primer tag PropertyGroup. Este será el lenguaje neutral de la aplicación.

  • Crear un archivo de recursos para el Lenguaje Neutral (Shell.resx) y añadir una entrada por cada control que se necesite localizar:

    • Para añadir otro idioma copiar y pegar el archivo de recursos (Shell.resx) y renombrarlo a Shell.es-ES.resx. Traducir todas las etiquetas a español, en este caso.

    • Para localizar una vista (un archivo .xaml):

      • Añadir una referencia a la librería de WPFLocalizeExtension. xmlns:loc="clr-namespace:LocalizeExtension.Localization;assembly=LocalizeExtension".

      • Para la propiedad que haya que traducir utilizar: {loc:LocText loc:Key=CustomerLabel, loc:Dict=Shell, loc:Assembly=MyAssembly.Shell}.

      • Key: Es el nombre del texto a mostrar.

      • Dict: Es el nombre del archivo de recursos.

      • Assembly: Es la dll donde se encuentra el archivo de recursos.

  • Compilar.

Este proceso es mucho menos complejo que el estándar y facilita bastante las cosas como se puede ver.

A program on your computer has corrupted your default search provider setting for Internet Explorer

Hace unas semanas el Windows Update decidió actualizar mi versión de Explorer de la versión 7 a la 8 en mi Windows XP. Desde entonces al abrir el explorer ha estado apareciendo el siguiente mensaje de error:

“A program on your computer has corrupted your default search provider setting for Internet Explorer.

Internet Explorer has reset this setting to your original search provider, Live Search (search.live.com).

Internet Explorer will now open Search Settings, where you can change this setting or install more search providers.”

La solución al problema es bastante sencilla:

  1. Con el IE 8 cerrado ir a esta clave de registro: HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersion ExplorerUser Shell Folders.

  2. Añadir una nueva clave de registro del tipo Expandable String value. Con la key AppData y el campo value %USERPROFILE%Application Data.

  3. Abrir el IE 8 y verificar que no vuelve a salir el mensaje.