Microsoft e Intel anuncian Silverlight para Moblin

septiembre 26, 2009 11:34 by EugenioEstrada

Microsoft e Intel acaban de anunciar el desarrollo de una implementación especifica de Silverlight para el S.O. basado en Linux de Intel, Moblin. Dicho sistema operativo tiene un repositorio de aplicaciones similar al del iPhone, donde sería distribuída dicho paquete.

Ha llamado especialmente la atención este anuncio ya que ya existe una implementación de Silverlight para Linux, Moonlight, tras el amparo de Novell. Pero Microsoft e Intel han justificado una nueva implementación en que mientras que Novell, con Moonlight, su target son S.O. de escritorio. Microsoft seguirá desarrollando implementaciones especificas, como puede ser la de Moblin, la de Nokia, etc. Ya que está sería con la ayuda de Intel para conseguir una mejor experiencia en equipos basados en Atom.

Para más información:

Programa de desarrollo de Intel Atom: http://appdeveloper.intel.com/en-us/
Moblin: http://moblin.org/
Moonlight: http://www.mono-project.com/Moonlight
Noticia: http://www.theregister.co.uk/2009/09/24/silverlight_to_linux/


Sea el primero en calificar este post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Silverlight: Como cambiar el titulo de la pagina

mayo 25, 2009 16:56 by eugenioestrada

En los foros de Silverlight preguntaban como enlazar el título de una página a un control. El problema está en que Silverlight por defecto no tiene una propiedad que nos permita acceder directamente al título de la página. Esto es debido a que Silverlight no está concebido para una relación uno a uno (HTML-Silverlight) sino como una forma de complementar la página HTML. Pero en cambio si que propone un sistema de interacción entre ambos mundos.

Por lo tanto, para poder abordar dicho problema crearé una clase llamada PageUtil:

using System.Windows.Browser;

public class PageUtil
{
    public static string PageTitle
    {
        get
        {
            var result = "";
            var elements =
                HtmlPage.Document.GetElementsByTagName("Title");
            if (elements != null && elements.Count > 0)
            {
                var titleElement = (HtmlElement)elements[0];
                result = (string)titleElement.GetProperty("innerHTML");
            }
            return result;
        }
        set
        {
            HtmlPage.Document.SetProperty("title", value);
        }
    }
}

Una vez que ya tenemos la clase creada debemos crear el recurso, ya sea a nivel local en el UserControl o a nivel de aplicación (para una clase tan genérica yo recomiendo que sea a nivel de aplicación).

<MyProject:PageUtil x:Key="PageUtilDataSource" /> 

Y luego solamente tenemos que enlazar la propiedad al control queramos:

<TextBox DataContext="{Binding Source={StaticResource PageUtilDataSource}}"
         Text="{Binding Path=PageTitle, Mode=TwoWay}"
         Height="30"
         VerticalAlignment="Top" />

Recuerdo que a mayores de hacer el enlace (en nuestro caso en la propiedad Text) debemos establecerle el DataContext con el recurso.

Como siempre espero que os sea útil.

Follow me! http://twitter.com/eugenioestrada


Sea el primero en calificar este post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Silverlight: El sistema de ficheros y configuraciones

mayo 22, 2009 00:26 by eugenioestrada

Una de las grandes limitaciones que tiene Silverlight es el acceso a disco, esto es debido a su ejecución aislada dentro del navegador. Habréis leído que Silverlight 3 tendrá capacidades de ejecución offline y out-of-browser, el resultado será el mismo ya que funcionaría igual que si siguiera alojada en el navegador.

Por muchos motivos podemos querer persistir en local algunos datos que hemos generado o que nos hemos traído del servidor.

Para ello Silverlight nos propone el Isolated Storage (almacenamiento aislado) donde podemos guardar ficheros y crear una jerarquía de carpetas. Antes de seguir quería comentar donde se encuentran estos directorios en la máquina:

  • Windows Vista/7: C:\Users\<Usuario>\AppData\LocalLow\Microsoft\Silverlight\is
  • Windows XP: C:\Documents and Settings\<Usuario>\Local Settings\Application Data\Microsoft\Silverlight\is
  • Mac OS X: /Users/<Usuario>/Library/Application Support/Microsoft/Silverlight/is

Dentro de esas carpetas lo organiza por grupos, definiendo un grupo por dominio (definiendo dominio como nombre de dominio, puerto y protocolo). De tal forma que los siguientes serían grupos diferentes:

En cambio los siguientes serían el mismo grupo:

La importancia de conocer estos grupos es que a cada grupo el Isolated Storage le va a asignar una cuota de espacio en disco. Por defecto esta cuota está establecida en 1.0 MB ya que para pequeñas configuraciones y un uso “standard” del Isolated Storage sería suficiente. Pero aún así, previo ser aceptado por el usuario esta se puede aumentar a voluntad del programador.

Pero ya ha llegado el momento de usarla. Principalmente tenemos dos clases con las que debemos jugar IsolatedStorageFile y IsolatedStorageSettings. La primera es para todo lo que he dicho hasta ahora acceso a disco, ficheros, carpetas, etc. IsolatedStorageSettings, en cambio, nos sirve para guardar objetos binarios.

El funcionamiento de ambas es muy sencillo, lo vamos a ver mejor con un ejemplo:

var store = 
IsolatedStorageFile.GetUserStoreForApplication(); using (var stream = store.CreateFile("Fichero.txt")) using (var writer = new StreamWriter(stream)) { writer.WriteLine("1"); writer.WriteLine("2"); }

Con la función IsolatedStorageFile.GetUserStoreForSite() podríamos obtener el Store del grupo o sitio. Y tras ejecutar el código, ahí tenemos el fichero:

image 

El store tiene muchos métodos a mayores, para comprobar si existe un fichero, ver y modificar la cuota, leer ficheros, crear directorios, etc.

En cambio con el IsolatedStorageSettings es mucho más simple:

IsolatedStorageSettings.ApplicationSettings["Fondo"] =
Colors.Blue;

También tenemos el SiteSettings donde podremos cambiar todas las propiedades a nivel de sitio.

Silverlight es bastante potente a nivel de sistema de ficheros, está limitado a su vez por la isla en la que encuentra,pero que debido a la anatomía de las aplicaciones Silverlight no debería de ser eso un problema.

Los comentarios son bienvenidos ;-)

Follow me! http://twitter.com/eugenioestrada


Sea el primero en calificar este post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tutorial: Usando el Visual State Manager

mayo 16, 2009 14:03 by EugenioEstrada

image

Tras varios meses trabajando con Silverlight uno empieza a tener buenas práctivas y ver como es más productivo. Por la forma de programar con Silverlight nos obliga a manipular el layout de nuestra aplicación constantemente. Para ello tenemos tres opciones: programáticamente desde C#, con StoryBoards o usando el Visual State Manager (VSM a partir de ahora).

Para nuestro tutorial vamos a crear un control llamado AnimatedImage con un UserControl normal con un Image dentro.

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	x:Class="EugenioEstrada.AnimatedImage"
	Width="Auto" Height="Auto">
	<Grid x:Name="LayoutRoot">
		<Image x:Name="InternalImage">
		
		</Image>
	</Grid>
</UserControl>

Lo que queremos hacer con este control es sencillo, que al pasar el Mouse por encima de la imagen ésta se escale un 1,5. Y luego que al hacer Click (controlando el MouseDown y MouseUp del ratón) haga una animación. Para hacer las animaciones debemos definir los RenderTransform tanto del Grid como del Image:

<Grid x:Name="LayoutRoot" RenderTransformOrigin="0.5,0.5">
	<Grid.RenderTransform>
		<TransformGroup>
			<ScaleTransform/>
        		<RotateTransform/>
    			<SkewTransform/>
</TransformGroup> </Grid.RenderTransform> <Image x:Name="InternalImage" RenderTransformOrigin="0.5,0.5"> <Image.RenderTransform> <TransformGroup> <ScaleTransform/> </TransformGroup> </Image.RenderTransform> </Image> </Grid>

Sólo hemos definido el Scale, Rotate y Skew porque son los únicos que vamos a modificar luego. Y el RenderTransformOrigin define que el origen de las transformaciones será el punto central del elemento. Dentro del Grid vamos a definir el VSM y también debemos importar el namespace del VSM. Quedando así al final:

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:w="clr-namespace:System.Windows;assembly=System.Windows"
	x:Class="EugenioEstrada.AnimatedImage"
	Width="Auto" Height="Auto">
	<Grid x:Name="LayoutRoot" RenderTransformOrigin="0.5,0.5">
		<Grid.RenderTransform>
			<TransformGroup>
				<ScaleTransform/>
        			<RotateTransform/>
<SkewTransform/>
       </TransformGroup>
</Grid.RenderTransform>
        <w:VisualStateManager.VisualStateGroups>
<!-- A partir de ahora aquí -->
</w:VisualStateManager.VisualStateGroups>
        <Image x:Name="InternalImage" RenderTransformOrigin="0.5,0.5">
     <Image.RenderTransform>
        <TransformGroup>
        <ScaleTransform/>

        </TransformGroup>
        </Image.RenderTransform>
     </Image>
    </Grid>
</UserControl>

Ahora seguiremos dentro del VisualStateGroups, para hacernos una idea de como funciona el VSM  este define ciertos grupos de estados, por ejemplo para poder agrupar por estados que responden al mouse, estados comunes, etc. Sirve para agrupar estados de forma lógica reduciendo la combinatoria de éstos. Luego cada estado lo define un StoryBoard, que es el que establecerá el estado de la UI y luego se podrían definir transiciones entre estados para que no haya inconsistencias en el diseño. En nuestro caso solamente tendremos tresestados: Normal, MouseOver, MouseUp y todos los agruparemos en el VisualStateGroup que llamaremos CommonStates.

<w:VisualStateGroup x:Name="CommonStates">
	<w:VisualState x:Name="Normal"/>
	<w:VisualState x:Name="MouseOver"/>
	<w:VisualState x:Name="MouseUp"/>
</w:VisualStateGroup>

Para hacer esto recomiendo el uso de Microsoft Expression Blend (http://expression.microsoft.com) ya que es mucho más sencillo:

image

Empezaremos definiendo el estado Normal para verlo de ejemplo lo que hará es que desde un escalado del 150% pasará al 100% y esto se haría así:

<w:VisualState x:Name="Normal">
    <Storyboard>
        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
            Storyboard.TargetName="InternalImage"
            Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
            <EasingDoubleKeyFrame KeyTime="00:00:00" Value="1.5"/>
            <EasingDoubleKeyFrame KeyTime="00:00:00.2000000" Value="1"/>
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
            Storyboard.TargetName="InternalImage"
            Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
            <EasingDoubleKeyFrame KeyTime="00:00:00" Value="1.5"/>
            <EasingDoubleKeyFrame KeyTime="00:00:00.2000000" Value="1"/>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</w:VisualState>

 

Lo más complicado es el entender el TargetProperty que es el siguiente:

Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"

No es un acceso intuitivo (del estilo InternalImage.ScaleTransform.ScaleY) esto se debe a como funcionan las DependencyProperties de WPF/Silverlight que nos dará tema para otro artículo. Pero para hacer una vista muy rápida se debe a que las DependencyProperties son métodos estáticos que se encargan de hacer el get y el set mediante eventos. Esto nos permite luego usar todas capacidades de Data Binding que tiene tanto WPF como Silverlight. De una forma muy parecida vamos a crear los otros dos estados:

<w:VisualState x:Name="MouseOver">
	<Storyboard>
		<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="InternalImage"
			Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
			<EasingDoubleKeyFrame KeyTime="00:00:00.2000000" Value="1.5"/>
		</DoubleAnimationUsingKeyFrames>
		<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="InternalImage"
			Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
			<EasingDoubleKeyFrame KeyTime="00:00:00.2000000" Value="1.5"/>
		</DoubleAnimationUsingKeyFrames>
	</Storyboard>
</w:VisualState>
<w:VisualState x:Name="MouseUp">
	<Storyboard>
	    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="LayoutRoot"
			Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
			<EasingDoubleKeyFrame KeyTime="00:00:00.1000000" Value="30"/>
			<EasingDoubleKeyFrame KeyTime="00:00:00.2000000" Value="-30"/>
			<EasingDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0"/>
		</DoubleAnimationUsingKeyFrames>
	</Storyboard>
</w:VisualState>

Ahora llega el momento de escribir un poco de C#. Debemos manejar los eventos MouseMove, MouseLeave y MouseLeftButtonUp del InternalImage:

<Image x:Name="InternalImage"
	RenderTransformOrigin="0.5,0.5"
MouseMove="InternalImage_MouseMove"
MouseLeftButtonUp="InternalImage_MouseLeftButtonUp"
MouseLeave="InternalImage_MouseLeave">

 

Y la clase AnimatedImage queda de la siguiente forma con los manejadores de eventos:

using System.Windows;
using System.Windows.Controls;

namespace EugenioEstrada
{
	public partial class AnimatedImage : UserControl
	{
		public AnimatedImage()
		{
			InitializeComponent();
			VisualStateManager.GoToState(this, "Normal", false);
		}

		private void InternalImage_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
		{
			VisualStateManager.GoToState(this, "MouseOver", false);
		}

		private void InternalImage_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
		{
			VisualStateManager.GoToState(this, "MouseUp", false);
		}

		private void InternalImage_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
		{
			VisualStateManager.GoToState(this, "Normal", false);
		}
	}
}

VisualStateManager es una clase estática y la firma de su método GoToState es la siguiente:

public static bool GoToState(Control control, string stateName, bool useTransitions);

El parámetro control es aquel objeto que queremos cambiarle el estado, el stateName es el nombre del estado al que queremos cambiar y el último parámetro, useTransitions, se usa para establecer si se usarán las transiciones de estado o no, en nuestro caso como no hemos definido ninguna lo establecemos en false.

Y finalmente el resultado es el siguiente:

Tras este artículo se nos abren varias opciones de publicación como Dependency Properties, Data Binding, etc.

 http://twitter.com/eugenioestrada (tweet me!)


Actualmente calificado con 5.0 por 1 personas

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5