<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Juanma Santoyo &#187; surface</title>
	<atom:link href="http://www.juanmasantoyo.es/index.php/category/surface/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.juanmasantoyo.es</link>
	<description>En ocasiones me llaman friki</description>
	<lastBuildDate>Thu, 19 Jan 2012 06:33:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Instalar el entorno de desarrollo de Surface 2</title>
		<link>http://www.juanmasantoyo.es/index.php/2011/08/01/instalar-el-entorno-de-desarrollo-de-surface-2/</link>
		<comments>http://www.juanmasantoyo.es/index.php/2011/08/01/instalar-el-entorno-de-desarrollo-de-surface-2/#comments</comments>
		<pubDate>Mon, 01 Aug 2011 15:34:04 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[surface]]></category>

		<guid isPermaLink="false">http://www.juanmasantoyo.es/?p=637</guid>
		<description><![CDATA[Instalar el entorno de desarrollo para la Surface 2 es relatívamente sencillo, ya que el proceso es similar a la instalación del entorno para Surface 1. De hecho es más sencillo si cabe, ya que en ésta ocasión la instalación &#8230; <a href="http://www.juanmasantoyo.es/index.php/2011/08/01/instalar-el-entorno-de-desarrollo-de-surface-2/">Seguir leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Instalar el entorno de desarrollo para la Surface 2 es relatívamente sencillo, ya que el proceso es similar a la instalación del entorno para Surface 1. De hecho es más sencillo si cabe, ya que en ésta ocasión la instalación es totalmente compatible con Windows 7 y Visual Studio 2010, por lo que nos ahorraremos problemas.</p>
<p>Paso a comentar qué hace falta instalar con sus respectivos enlaces de descarga.<br />
<span id="more-637"></span> Visual Studio 2010</p>
<p>Obviamente, lo primero es contar con un buen entorno de programación. Los que aún no tengáis un Visual Studio 2010 en vuestras manos, sabed que se pueden obtener licencias gratuitas desde el programa para estudiantes <a title="Dreamspark" href="https://www.dreamspark.com/default.aspx">Deamspark</a>. Si no sois estudiantes, podéis haceros con una versión de <a title="Visual C# 2010 Express" href="http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-csharp-express">Visual C# 2010 Express</a>, que no tiene tantas funcionalidades como un Visual Studio; pero es gratiíto y sigue siendo un bien IDE.</p>
<p>Mi recomendación es que os hagáis con las versiones en inglés.</p>
<h3>XNA Framework redistributable 4.0</h3>
<p>Al igual que el SDK de Surface 1 requería del XNA Framework redistributable 2.0, para el SDK de Surface 2 necesitaremos el <a title="XNA Framework redistributable 4.0" href="http://www.microsoft.com/download/en/details.aspx?id=20914">XNA Framework redistributable 4.0</a>. Se puede descargar fácilmente desde el centro de descargas de Microsoft.</p>
<h3>SDK de Surface 2</h3>
<p>Ahora ya tenemos todo lo que necesitamos para instalar el <a title="Surface 2 SDK" href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;id=26716">SDK de Surface 2</a>. También se puede bajar desde el centro de descargas de Microsoft.</p>
<h3>Empezar a programar con el nuevo SDK</h3>
<p>Para empezar a tocar, podéis echarle un ojo a la <a title="Documentación de Surface 2 SDK en MSDN" href="http://msdn.microsoft.com/en-us/library/ff727815(Surface.20).aspx">nueva documentación de MSDN</a>.</p>
<p>¡A Programar!. Hay que hacer una mención especial a la nueva interfaz metro, y las nuevas herramientas de desarrollo. Ahora el emulador está totalmente integrado en Windows 7 y es mucho más agradable para los desarrolladores. Sobre todo si contamos con una pantalla táctil.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.juanmasantoyo.es/index.php/2011/08/01/instalar-el-entorno-de-desarrollo-de-surface-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Crear eventos propios en aplicaciones de Surface</title>
		<link>http://www.juanmasantoyo.es/index.php/2010/10/02/crear-eventos-propios-en-aplicaciones-de-surface/</link>
		<comments>http://www.juanmasantoyo.es/index.php/2010/10/02/crear-eventos-propios-en-aplicaciones-de-surface/#comments</comments>
		<pubDate>Sat, 02 Oct 2010 08:34:41 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[surface]]></category>

		<guid isPermaLink="false">http://www.juanmasantoyo.es/?p=535</guid>
		<description><![CDATA[En las aplicaciones de Surface, los eventos son básicos. La mayoría de las veces, nos bastará con los eventos que nos proporciona el SDK, pero en ocasiones necesitamos algo más específico, o incluso reaccionar a una combinación de eventos. Necesitamos &#8230; <a href="http://www.juanmasantoyo.es/index.php/2010/10/02/crear-eventos-propios-en-aplicaciones-de-surface/">Seguir leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>En las aplicaciones de Surface, los eventos son básicos.</p>
<p>La mayoría de las veces, nos bastará con los eventos que nos proporciona el SDK, pero en ocasiones necesitamos algo más específico, o incluso reaccionar a una combinación de eventos. Necesitamos eventos propios: poder disparar el evento cuando queramos, pasar la información que queramos; y que otra clase que esté escuchando el evento realice una acción.</p>
<p>De eso hablaré en este artículo. Comentaré un pequeño ejemplo donde veremos cómo podemos implementar un evento de doble tap (lo llamaremos <em>DoubleTap</em>). Este evento no viene implementado en el SDK de Surface, y como análogo al por todos conocido &#8220;Doble Click&#8221; de los PC, puede resultar muy útil.</p>
<p><span id="more-535"></span></p>
<h3>Implementación de un evento DoubleTap.</h3>
<p>Vamos a organizarnos un poco: ¿cómo vamos a implementar el <em>DoubleTap</em>?. Pues bien, en esencia un <em>DoubleTap</em> no es más que dos <em>ContactDown </em>en un periodo corto de tiempo. El <em>ContactDown </em>es un evento que sí que viene implementado en el SDK, así que sólo necesitamos almacenar el instante en el que se realizó el primer <em>ContactDown </em>para comprobar si el tiempo entre dos <em>ContactDown </em>es lo suficientemente corto. De serlo, se dispararía el <em>DoubleTap</em>. Es decir, que necesitamos:</p>
<ul>
<li>Un manejador para el evento <em>ContactDown</em>.</li>
<li>Una propiedad global de tipo <em>DateTime </em>que almacenará el momento del último <em>ContactDown</em>.</li>
</ul>
<p>Todo esto lo programaríamos dentro del objeto al que queremos dotar de la capacidad de lanzar <em>DoubleTap</em>. En nuestro caso, será un control de usuario (lo normal).</p>
<h3>Programamos el control de usuario.</h3>
<p>Gráficamente lo haremos fácil: un rectángulo. Este es el <em>XAML</em>:</p>
<pre class="brush:xml">&lt;s:SurfaceUserControl x:Class="ProgramarEventosPropios.DoubleTapUserControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:s="http://schemas.microsoft.com/surface/2008"&gt;
    &lt;Grid&gt;
        &lt;Rectangle Fill="Red" Width="100" Height="100" /&gt;
    &lt;/Grid&gt;
&lt;/s:SurfaceUserControl&gt;</pre>
<p>Y ahora, el<em> C#</em>. Aquí es donde programaremos el evento <em>DoubleTap</em>, pero primero, vayamos a lo principal: gestionar el evento <em>ContactDown</em> y el tiempo entre dos <em>ContactDown</em>:</p>
<pre class="brush:csharp">DateTime LastContactDown = DateTime.MinValue;
TimeSpan MaxMilis = TimeSpan.FromMilliseconds(700);

protected override void OnContactDown(ContactEventArgs e)
{
    base.OnContactDown(e);

    if (this.LastContactDown == DateTime.MinValue)
    {
        this.LastContactDown = DateTime.Now;
    }
    else
    {
        TimeSpan time = DateTime.Now - this.LastContactDown;

         if (time &lt;= this.MaxMilis)
         {
             RaiseDoubleTapEvent(time);
         }

         this.LastContactDown = DateTime.MinValue;
    }
}</pre>
<p>Varias cosas a comentar de este código:</p>
<ol>
<li>La variable <em>MaxMilis </em>sólo define el tiempo máximo entre <em>ContactDown</em>. Únicamente cuando el tiempo es inferior o igual, se considera un <em>DoubleTap</em>.</li>
<li>Por otra parte, mirad cómo asigno el evento <em>ContactDown</em>. Lo normal es asignar un manejador, pero en este caso hago una sobreescritura del método <em>OnContactDown</em>. Los eventos también se pueden asignar así, aunque sinceramente, yo prefiero añadir un manejador en el <em>XAML </em>(en esta ocasión lo hago con sobreescritura a modo ilustrativo).</li>
<li>Por último, fijaos que en caso de cumplirse el <em>DoubleTap</em>, ejecuto el método <em>RaiseDoubleTapEvent </em>con el parámetro <em>time</em>. El método lo veremos ahora, se trata del disparador del evento. Los disparadores no son necesarios, pero sí muy recomendables. El parámetro time lo paso por que es la información que quiero enviar con el evento (en un objeto <em>EventArgs</em>). De esta forma, los manejadores del evento <em>DoubleTap </em>pueden saber cuánto tiempo pasó entre los dos <em>ContactDown </em>(no es una información demasiado útil, pero para ilustrar como funcionan los objetos <em>EventArgs </em>nos viene de perlas).</li>
</ol>
<p>Y ahora empieza lo bueno: programamos el evento.</p>
<p>En realidad, hay que programar varias cosas:</p>
<ol>
<li>El evento.</li>
<li>Las gestión de los manejadores que quieran escuchar el evento.</li>
<li>Un disparador para el evento.</li>
</ol>
<h4>Programamos el evento.</h4>
<p>En realidad lo único complejo es el registro del evento. Y no es que sea complejo, es sólo que es muy configurable (y requiere muchos parámetros).</p>
<pre class="brush:csharp">public delegate void DoubleTapEventHandler(object sender, DoubleTapEventArgs e);

public static readonly RoutedEvent DoubleTapEvent = EventManager.RegisterRoutedEvent(
	"DoubleTap",
	RoutingStrategy.Direct,
	typeof(DoubleTapEventHandler),
	typeof(DoubleTapUserControl));</pre>
<p>Lo primero, definimos el manejador del evento. Le damos nombre, y; sobre todo; determinamos que los argumentos vienen como un objeto <em>DoubleTapEventArgs</em>. Este objeto lo crearemos luego, y tiene la particularidad de tener una propiedad para almacenar el tiempo entre los dos <em>ContactDown </em>¿recordáis que al disparador le pasábamos un parámetro <em>time</em>?.</p>
<p>En cuanto al registro del evento, le pasamos cuatro parámetros:</p>
<ol>
<li>El nombre del evento.</li>
<li>La estrategia del evento. Puede ser <em>Direct</em>, <em>Tunnel </em>o <em>Bubble</em>. Sirve para determinar la dirección de propagación. En este caso, <em>Direct </em>no se propaga.</li>
<li>El tipo del manejador. No es casualidad que coincida con lo declarado en la línea 1.</li>
<li>El tipo del objeto que dispara el evento. En este caso, el nombre de nuestro control de usuario.</li>
</ol>
<h4>La gestión de manejadores.</h4>
<p>Esto se parece a los típicos <em>getters </em>/ <em>setters</em> de .Net. Se trata simplemente de gestionar lo que ocurre cuando se añaden o se quitan manejadores de los eventos.</p>
<pre class="brush:csharp">public event DoubleTapEventHandler DoubleTap
{
    add
    {
        AddHandler(DoubleTapEvent, value);
    }
    remove
    {
        RemoveHandler(DoubleTapEvent, value);
    }
}</pre>
<h4>El disparador.</h4>
<p>Este método se encarga de lanzar el evento. Un disparador debería hacer tres cosas:</p>
<ol>
<li>Recibir por parámetro los valores que hay que enviar como argumentos del evento.</li>
<li>Montar un objeto <em>EventArgs</em> que contenga los valores a enviar.</li>
<li>Lanzar el evento.</li>
</ol>
<p>Es muy sencillo:</p>
<pre class="brush:csharp">private void RaiseDoubleTapEvent(TimeSpan TimeBetweenTaps)
{
    DoubleTapEventArgs Args = new DoubleTapEventArgs(TimeBetweenTaps);
    Args.RoutedEvent = DoubleTapUserControl.DoubleTapEvent;

    RaiseEvent(Args);
}</pre>
<p>Y este sería el objeto <em>DoubleTapEventArgs</em>. La idea es que es una extensión del objeto <em>RoutedEventArgs</em>.</p>
<pre class="brush:csharp">public class DoubleTapEventArgs : RoutedEventArgs
{
	TimeSpan timeBetweenTaps = TimeSpan.MinValue;
	public TimeSpan TimeBetweenTaps
	{
	  get { return timeBetweenTaps; }
	}

	public DoubleTapEventArgs(TimeSpan TimeBetweenTaps) : base()
	{
		this.timeBetweenTaps = TimeBetweenTaps;
	}
}</pre>
<p>Con esto ya hemos programado un control de usuario capaz de detectar y disparar un evento <em>DoubleTap</em>. ¿Cómo lo usamos?. Vamos a añadir este objeto a la ventana inicial de la aplicación y lo vemos. En realidad, como si fuese un evento normal y corriente.</p>
<p>Este es el <em>XAML </em>de la ventana:</p>
<pre class="brush:xml">&lt;s:SurfaceWindow x:Class="ProgramarEventosPropios.SurfaceWindow1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:s="http://schemas.microsoft.com/surface/2008"
    xmlns:self="clr-namespace:ProgramarEventosPropios"
    Title="ProgramarEventosPropios"
&gt;
    &lt;s:SurfaceWindow.Resources&gt;
        &lt;ImageBrush x:Key="WindowBackground" Stretch="None" Opacity="0.6" ImageSource="pack://application:,,,/Resources/WindowBackground.jpg"/&gt;
    &lt;/s:SurfaceWindow.Resources&gt;

    &lt;Grid Background="{StaticResource WindowBackground}" &gt;
        &lt;self:DoubleTapUserControl x:Name="DoubleTapUC" DoubleTap="DoubleTapUC_DoubleTap" /&gt;
    &lt;/Grid&gt;</pre>
<p>Y desde el C# programamos el manejador del evento:</p>
<pre class="brush:csharp">void DoubleTapUC_DoubleTap(object sender, DoubleTapEventArgs e)
{
    Debug.WriteLine("Double Tap. Tiempo: {0}", e.TimeBetweenTaps.TotalMilliseconds);
}</pre>
<h3>Descarga del ejemplo.</h3>
<p>Y como no podía ser de otra forma, os dejo aquí la descarga a un pequeño proyecto que es el que programé para redactar este artículo.</p>
<p><a href="http://www.juanmasantoyo.es/wp-content/uploads/2010/10/CrearEventosPropios.zip">Crear eventos propios.</a></p>
<h3>¡Hemos acabado!.</h3>
<p>Con esto ya tenemos un evento propio funcionando. Este tipo de eventos nos serán muy útiles en nuestras aplicaciones, y nos solucionarán la vida en muchas ocasiones. No está de más decir que realmente este tipo de eventos se pueden implementar en cualquier aplicación WPF, no sólo en las aplicaciones de Surface.</p>
<p>Espero que hayáis encontrado útil este artículo.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.juanmasantoyo.es/index.php/2010/10/02/crear-eventos-propios-en-aplicaciones-de-surface/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Arquitectura de capas en aplicaciones para Microsoft Surface</title>
		<link>http://www.juanmasantoyo.es/index.php/2010/09/30/arquitectura-de-capas-en-aplicaciones-para-microsoft-surface/</link>
		<comments>http://www.juanmasantoyo.es/index.php/2010/09/30/arquitectura-de-capas-en-aplicaciones-para-microsoft-surface/#comments</comments>
		<pubDate>Thu, 30 Sep 2010 19:10:46 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[surface]]></category>

		<guid isPermaLink="false">http://www.juanmasantoyo.es/?p=521</guid>
		<description><![CDATA[En la primera aplicación que hice para Surface, cometí un gran error de arquitectura que bajo mi punto de vista estropeó un poco lo que yo considero que fue un buen trabajo. Ahora que estoy trabajando en otra aplicación para &#8230; <a href="http://www.juanmasantoyo.es/index.php/2010/09/30/arquitectura-de-capas-en-aplicaciones-para-microsoft-surface/">Seguir leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>En <a href="http://www.juanmasantoyo.es/index.php/2010/07/06/video-de-rent-a-car-surface-by-bizzit/">la primera aplicación que hice para Surface</a>, cometí un gran error de arquitectura que bajo mi punto de vista estropeó un poco lo que yo considero que fue un buen trabajo. Ahora que estoy trabajando en otra aplicación para Surface, me propuse desde el primer día no repetirlo. A la solución que he encontrado la he llamado arquitectura de capas. No estoy inventando nada, pues en la programación gráfica dividir la interfaz  en capas es muy común. Este artículo realmente sólo propone una forma de  hacerlo en una aplicación WPF orientada a Surface.<br />
<span id="more-521"></span></p>
<h3>Mi gran error.</h3>
<p>Me dí cuenta de que era realmente complicado gestionar las cosas que había en el <em>ScatterView</em>. Si veis el vídeo, comprobaréis que básicamente estoy hablando de tres tipos de elementos: los controles de usuario, el coche, y las imágenes del interior del coche. La solución por la que opté en aquel momento se basaba en usar métodos para introducir y eliminar cada elemento en el <em>ScatterView</em>, y registrar la existencia de cada uno en tres listas globales (una lista para cada tipo de elemento). De esa forma ponía y quitaba los elementos de cada tipo.</p>
<p>Era una mala solución, por que no permitía una gran modularización del código y sobrecargaba la clase principal del programa de funcionalidades que realmente no eran de su competencia. Todo se complicaba mucho más si tenemos en cuenta que no pude encapsular el <em>ScatterView </em>en un control de usuario como me hubiese gustado y lo tenía todo en la ventana inicial de la aplicación. En pocas palabras, aunque creo que algunos aspectos de la aplicación quedaron bastante bien, la ventana inicial era sucia y desordenada. El tiempo y la falta de experiencia me impidieron mejorar ese aspecto. Se podría decir que esa aplicación tiene un serio problema de arquitectura.</p>
<h3>La solución: Arquitectura de capas.</h3>
<p>Sin embargo, cuando inicié el desarrollo de la aplicación que tengo ahora entre manos, decidí desde el primer momento plantear las cosas de otro modo. No quería repetir el mismo error, sobre todo por que esta aplicación es aún más compleja en lo que respecta a los elementos libres por la pantalla y un error de esas características hubiese tenido un impacto negativo en la aplicación mucho más devastador.</p>
<p>El principal error que cometí inicialmente fue pensar que un <em>ScatterView </em>no puede posicionarse sobre otro. En realidad, sí es posible, y ambos <em>ScatterViews </em>son totalmente funcionales. Esto nos permite organizar los elementos en varios <em>ScatterViews</em>, uno sobre otro; como si fuesen capas.</p>
<p>Básicamente, para implementar esta arquitectura sólo necesitaremos:</p>
<ol>
<li>Diferentes controles de usuario que serán las capas.</li>
<li>Una clase estática o Singleton que se encargará de gestionar las interacciones entre capas.</li>
</ol>
<p>Cada capa se preocupa únicamente de sus competencias, mientras que para cualquier tipo de interacción con los elementos de las otras capas se usarán funcionalidades implementadas en la clase estática.</p>
<h3>Un ejemplo sencillo.</h3>
<p>No voy a complicarlo, ya que realmente sólo nos interesa ver cómo funcionaría esta arquitectura.</p>
<p>El ejemplo en cuestión será el siguiente: vamos a hacer dos capas en forma de controles de usuario. En cada capa vamos a poner un <em>ScatterView </em>y un <em>ScatterViewItem</em>.</p>
<p>La idea es que cuando un <em>ScatterViewItem </em>se mueva, el otro se posicionará en una posición reflejada. Es decir, reflejará las coordenadas X e Y del <em>ScatterViewItem </em>que hemos movido.</p>
<p>Obviamente, la comunicación entre controles de usuario que necesitamos se implementará con una clase estática.</p>
<h4>Las capas.</h4>
<p>Vamos a programar las dos capas. Serán dos controles prácticamente idénticos, sólo cambiaremos un par de características del <em>ScatterViewItem </em>(para que no se confundan). Los <em>ScatterViewItems </em>tendrán colores diferentes y ubicaciones diferentes (obviamente). Uno estará situado en el punto (100, 100) y el otro en su punto simétrico (924, 668). Para simplificar el asunto, haremos que los <em>ScatterViewItems </em>no se puedan rotar ni escalar.</p>
<p>Los controles de usuario se llamarán LayerA y LayerB, este es su <em>XAML</em>:</p>
<h5>LayerA.</h5>
<pre class="brush:xml">&lt;s:SurfaceUserControl x:Class="ArquitecturaDeCapas.LayerA"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:s="http://schemas.microsoft.com/surface/2008"&gt;
    &lt;Grid&gt;
        &lt;s:ScatterView&gt;
            &lt;s:ScatterViewItem x:Name="Svi"
                Orientation="0" Center="100,100"
                Width="50" Height="50"
                CanScale="False" CanRotate="False"
                ScatterManipulationDelta="ScatterViewItem_ScatterManipulationDelta"
            &gt;
                &lt;Rectangle Fill="Yellow" /&gt;
            &lt;/s:ScatterViewItem&gt;
        &lt;/s:ScatterView&gt;
    &lt;/Grid&gt;
&lt;/s:SurfaceUserControl&gt;</pre>
<h5>LayerB.</h5>
<pre class="brush:xml">&lt;s:SurfaceUserControl x:Class="ArquitecturaDeCapas.LayerB"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:s="http://schemas.microsoft.com/surface/2008"&gt;
    &lt;Grid&gt;
        &lt;s:ScatterView&gt;
            &lt;s:ScatterViewItem x:Name="Svi"
                Orientation="0" Center="924,668"
                Width="50" Height="50"
                CanScale="False" CanRotate="False"
                ScatterManipulationDelta="ScatterViewItem_ScatterManipulationDelta"
            &gt;
                &lt;Rectangle Fill="Red" /&gt;
            &lt;/s:ScatterViewItem&gt;
        &lt;/s:ScatterView&gt;
    &lt;/Grid&gt;
&lt;/s:SurfaceUserControl&gt;</pre>
<p>Como veis en ambos controles, los <em>ScatterViewItems </em>tienen asignado un manejador para el evento &#8220;<em>ScatterManipilationDelta</em>&#8220;. Este evento se lanza cada vez que una manipulación provoca un cambio en el <em>ScatterViewItem</em>, así que lo usaremos para notificar a la clase estática que el <em>ScatterViewItem</em> tiene una nueva posición (y la clase estática lo notificará a su vez a la otra capa).</p>
<p>Vamos pues a ver ese manejador. En ambas capas será igual, ya que será el método de la clase estática quien diferencie entre una capa o otra (esto no tendría por qué ser así).</p>
<h5>El manejador de <em>ScatterManipilationDelta.</em></h5>
<pre class="brush:csharp">private void ScatterViewItem_ScatterManipulationDelta(object sender, ScatterManipulationDeltaEventArgs e)
{
    ScatterViewItem svi = (ScatterViewItem) sender;
    Layers.NotifyNewPosition(this, svi.Center);
}</pre>
<p>Fijaos en el método <em>Layers.NotifyNewPosition</em>. Este método será el método que comunicará ambas capas. La idea es que haga dos cosas:</p>
<ol>
<li>Identifica la capa que llama al método.</li>
<li>Notifica a la otra capa la nueva posición respecto a la que debe reflejar su <em>ScatterViewItem</em>.</li>
</ol>
<p>Para identificar la capa que llama al método, vemos que se envía el parámetro <em>this</em>. Para saber la nueva posición del <em>ScatterViewItem</em>, envía el parámetro <em>svi.Center</em>.</p>
<p>Por otra parte, la clase estática informará a la otra capa de la nueva posición mediante un método público en la capa que deba ser notificada. En este caso, como la posición se refleja; también se harán los cálculos necesarios. El método público de cada capa, sería una cosa así:</p>
<pre class="brush:csharp">
public void ReflexSviPosition(Point Position)
{
    this.Svi.Center = new Point(1024 - Position.X, 768 - Position.Y);
}
</pre>
<p>Ahora que ya sabemos como son las capas, vamos a ver que forma tiene esa clase estática que nos comunicará ambas capas.</p>
<h5>Una clase estática para comunicar las distintas capas.</h5>
<p>A la capa en cuestión la llamaremos Layers. Como he dicho, puede ser estática o Singletone. Aunque seamos francos, realmente el único requisito que debe cumplir esta clase es que tiene que ser accesible por todas las capas que queramos relacionar.</p>
<pre class="brush:csharp">public static class Layers
{
	private static LayerA layerA = null;
	public static LayerA LayerA
	{
		get { return layerA; }
		set { layerA = value; }
	}

	private static LayerB layerB = null;
	public static LayerB LayerB
	{
		get { return Layers.layerB; }
		set { Layers.layerB = value; }
	}

	public static void NotifyNewPosition(SurfaceUserControl Layer, Point Position)
	{
		if(Layer.GetType() == typeof(LayerA))
		{
			layerB.ReflexSviPosition(Position);
		}
		else if(Layer.GetType() == typeof(LayerB))
		{
			layerA.ReflexSviPosition(Position);
		}
	}
}</pre>
<p>Podéis ver el método &#8220;<em>NotifyNewPosition</em>&#8221; y cómo hace la distinción de capas.</p>
<p>Otro aspecto muy importante de esta clase, son las propiedades <em>LayerA </em>y <em>LayerB</em>. No son más que referencias a las capas, para poder acceder posteriormente a ellas. ¿Dónde se inician estas propiedades? Pues allí donde estén las propias capas. En este caso es la ventana inicial de mi programa, que se llama Main.xaml.</p>
<h5>El contenedor de las capas.</h5>
<p>Este sería el xaml:</p>
<pre class="brush:xml">&lt;s:SurfaceWindow x:Class="ArquitecturaDeCapas.Main"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:s="http://schemas.microsoft.com/surface/2008"
    xmlns:self="clr-namespace:ArquitecturaDeCapas"

    Title="ArquitecturaDeCapas"
&gt;
    &lt;s:SurfaceWindow.Resources&gt;
        &lt;ImageBrush x:Key="WindowBackground" Stretch="None" Opacity="0.6" ImageSource="pack://application:,,,/Resources/MainBackground.jpg"/&gt;
    &lt;/s:SurfaceWindow.Resources&gt;

    &lt;Grid Background="{StaticResource WindowBackground}"&gt;
        &lt;self:LayerA x:Name="LayerA" /&gt;
        &lt;self:LayerB x:Name="LayerB" /&gt;
    &lt;/Grid&gt;
&lt;/s:SurfaceWindow&gt;</pre>
<p>Y también se necesita un poco de <em>C#</em> para guardar en la clase <em>Layers</em> las referencias a cada capa. En mi caso, he añadido estas dos líneas de código al final del constructor de <em>Main</em>.</p>
<pre class="brush:csharp">Layers.LayerA = this.LayerA;
Layers.LayerB = this.LayerB;</pre>
<p>De esta clase <em>Main </em>destacar tres cosas:</p>
<ol>
<li>Añadimos el namespace <em>self</em>, para poder incluír controles de usuario de nuestro proyecto.</li>
<li>Añadimos las dos capas.</li>
<li>Guardamos en <em>Layers </em>las referencias a nuestras capas. Yo lo he hecho al final del constructor, pero se podría hacer en el evento <em>Loaded</em>, por ejemplo.</li>
</ol>
<h3>Hemos acabado.</h3>
<p>Pues no hay mucho más que decir, ya tenemos dos <em>ScatterViews </em>sincronizados. Rápido, sencillo, y para toda la familia; espero que os ayude.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.juanmasantoyo.es/index.php/2010/09/30/arquitectura-de-capas-en-aplicaciones-para-microsoft-surface/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Detección y gestión de contactos en una Surface</title>
		<link>http://www.juanmasantoyo.es/index.php/2010/09/22/deteccion-y-gestion-de-contactos-en-una-surface/</link>
		<comments>http://www.juanmasantoyo.es/index.php/2010/09/22/deteccion-y-gestion-de-contactos-en-una-surface/#comments</comments>
		<pubDate>Wed, 22 Sep 2010 17:55:16 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[surface]]></category>

		<guid isPermaLink="false">http://www.juanmasantoyo.es/?p=508</guid>
		<description><![CDATA[A estas alturas de la película, uno ya debería tener claro que la base de las entradas de usuario en una Surface son los contactos. Da igual si tocamos la pantalla con un dedo o con toda la mano, con &#8230; <a href="http://www.juanmasantoyo.es/index.php/2010/09/22/deteccion-y-gestion-de-contactos-en-una-surface/">Seguir leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A estas alturas de la película, uno ya debería tener claro que la base de las entradas de usuario en una Surface son los contactos.</p>
<p>Da igual si tocamos la pantalla con un dedo o con toda la mano, con un trozo de madera; o si hemos colocado un elemento etiquetado: Todo se reduce a detectar un contacto y gestionarlo.</p>
<p>Por lo tanto, se podría decir que hay varios tipos de contactos. En este artículo vamos a ver qué tipos de contactos hay, cómo podemos detectarlos, y cómo podemos obtener información relevante sobre los mismos. No es un asunto complicado, pero sí es bastante amplio. A modo de resumen, en el artículo vamos a tratar los siguientes puntos:</p>
<ol>
<li>Tipos de contactos.</li>
<li>Reconocimiento de contactos.</li>
<li>Diferenciación de contactos.</li>
<li>Reconocer el mismo contacto en diferentes eventos.</li>
<li>Conocer los diferentes contactos que existen sobre un elemento.</li>
</ol>
<p><span id="more-508"></span></p>
<h3>Tipos de contactos.</h3>
<p>Básicamente, podemos considerar tres tipos diferentes de contactos:</p>
<h4>Dedos.</h4>
<p>La mayoría de contactos son dedos, ya que para el usuario, lo más natural y intuitivo casi siempre será hacer algo con el dedo sobre la pantalla.</p>
<h4>Etiquetas.</h4>
<p>Una de las características más interesantes de una Surface es la detección de etiquetas. Las etiquetas son unos gráficos que al entrar en contacto con la pantalla son reconocidos como tales y tienen un valor numérico determinado.</p>
<p>Existen dos tipos de etiquetas: Las <em>Byte Tags</em> y las <em>Identity Tags</em>. La principal diferencia entre ambas es que las <em>Byte Tags</em> pueden tomar 2<sup>8</sup> valores distintos, y los <em>Identity Tags</em> pueden tomar 2<sup>128</sup> valores diferentes (separados en dos campos de 2<sup>64</sup> y 2<sup>64</sup>).</p>
<div id="attachment_510" class="wp-caption aligncenter" style="width: 81px"><a href="http://www.juanmasantoyo.es/wp-content/uploads/2010/09/ByteTagC6.jpg"><img class="size-full wp-image-510" title="Byte Tag" src="http://www.juanmasantoyo.es/wp-content/uploads/2010/09/ByteTagC6.jpg" alt="Byte Tag" width="71" height="71" /></a><p class="wp-caption-text">Un Byte Tag</p></div>
<div id="attachment_511" class="wp-caption aligncenter" style="width: 118px"><a href="http://www.juanmasantoyo.es/wp-content/uploads/2010/09/IdentityTag.png"><img class="size-full wp-image-511" title="Identity Tag" src="http://www.juanmasantoyo.es/wp-content/uploads/2010/09/IdentityTag.png" alt="Identity Tag" width="108" height="109" /></a><p class="wp-caption-text">Un Identity Tag</p></div>
<h4>Objetos.</h4>
<p>En realidad, la Surface reacciona ante cualquier contacto sobre la pantalla, sea lo que sea. Puede ser el dorso de la mano, un trozo de madera, etc. Por lo tanto, catalogaremos como un &#8220;objeto&#8221; cualquier contacto que no sea ni un dedo ni una etiqueta.</p>
<h3>Reconocer contactos sobre un elemento.</h3>
<p>Reconocer los contactos sobre un elemento es relativamente sencillo. El propio SDK nos aporta eventos como &#8220;<em>ContactDown</em>&#8220;, &#8220;<em>ContactUp</em>&#8221; o &#8220;<em>ContactTapGesture</em>&#8221; que nos realizaran dicha tarea. De hecho, &#8220;<em>ContactDown</em>&#8221; nos servirá en la mayoría de las ocasiones.</p>
<p>Lo que sí requiere más conocimiento del tema es cómo diferenciar los diferentes tipos de contactos, y cómo obtener información relevante sobre cada uno.</p>
<p>Veamos un ejemplo sencillo de &#8220;<em>ContactDown</em>&#8220;. Por ejemplo, sobre un control de usuario que tengamos en pantalla.</p>
<p>Añadiremos la gestión del evento en el <em>XAML</em> del Control de usuario:</p>
<pre class="brush:xml">&lt;s:SurfaceUserControl x:Class="DeteccionDeContactos.MyUserControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:s="http://schemas.microsoft.com/surface/2008"

    ContactDown="SurfaceUserControl_ContactDown"
    Width="100" Height="100"
&gt;
    &lt;Grid Background="Red"&gt;

    &lt;/Grid&gt;
&lt;/s:SurfaceUserControl&gt;</pre>
<p>Y esto nos generará en el código <em>C#</em> un método como este:</p>
<pre class="brush:csharp">private void SurfaceUserControl_ContactDown(object sender, ContactEventArgs e)
{
}</pre>
<p>Podéis ver que por parámetro nos llegan dos objetos. Uno es el objeto <em>sender</em>, que no es más que el control de usuario que ha recogido el evento &#8220;<em>ContactDown</em>&#8220;. Por otra parte, nos llega el objeto <em>e</em>. Es un objeto del tipo &#8220;<em>ContactEventArgs</em>&#8220;, y contiene mucha información que nos puede interesar.</p>
<h3>Obtener información útil sobre los contactos.</h3>
<p>Antes de nada, vamos a ver cómo podemos saber qué tipo de contacto es. En realidad es sencillo, ya que las propiedades <em>e.Contact.IsContactRecognized</em> y <em>e.Contact.IsTagRecognized </em>nos lo revelarán:</p>
<pre class="brush:csharp">private void SurfaceUserControl_ContactDown(object sender, ContactEventArgs e)
{
    if (e.Contact.IsFingerRecognized)
    {
        Debug.WriteLine("Es un dedo.");
    }
    else if (e.Contact.IsTagRecognized)
    {
        Debug.WriteLine("Es un elemento etiquetado.");
    }
    else
    {
        Debug.WriteLine("Es un objeto.");
    }
}</pre>
<p>Ahora bien: ¿Más cosas que nos puedan interesar? Pues dependerá del tipo de contacto, obviamente. En general, algo que tienen en común todos los contactos es una posición en pantalla y una orientación (recordemos que una de las más geniales características de una Surface es poder detectar la orientación de un contacto). Nos lo dirán los métodos <em>e.Contact.GetPosition</em> y <em>e.Contact.GetOrientation</em>. Ambos métodos reciben por parámetro un elemento respecto al que orientarse. Lo más común es orientarse respecto al objeto que capturó el método, así que el parámetro <em>sender</em> que mencioné antes nos viene de perlas. El objeto <em>sender</em> en principio viene tipado como un objeto genérico, así que habrá que hacerle un casting. No debería ser un problema si tenemos claro quien lanzó el evento.</p>
<pre class="brush:csharp">private void SurfaceUserControl_ContactDown(object sender, ContactEventArgs e)
{
    MyUserControl uc = (MyUserControl) sender;

    Point position = e.GetPosition(uc);
    Double orientation = e.Contact.GetOrientation(uc);

    Debug.WriteLine("El contacto se ha producido en la posición: {0}, {1}.", position.X, position.Y);
    Debug.WriteLine("La orientación del contacto es de {0} grados.", orientation);

    if (e.Contact.IsFingerRecognized)
    {
        Debug.WriteLine("Es un dedo.");
    }
    else if (e.Contact.IsTagRecognized)
    {
        Debug.WriteLine("Es un elemento etiquetado.");
    }
    else
    {
        Debug.WriteLine("Es un objeto.");
    }
}</pre>
<p>Bueno, ya sabemos dónde se produjo el contacto, y sabemos también su orientación. Si el contacto fuese un dedo, no necesitamos saber más. Pero ¿Y si es un objeto etiquetado? Hay dos parámetros importantísimos que nos interesará conocer: el tipo de etiqueta y su valor. Conviene anticipar que si el contacto es de tipo <em>Identity</em>, el valor se separa en dos campos: la serie y el valor. La serie son los primeros 2<sup>64</sup> bits, el valor son los últimos 2<sup>64</sup> bits. Debemos considerar el objeto <em>e.Contacts.Tag</em> y sus propiedades.</p>
<pre class="brush:csharp">private void SurfaceUserControl_ContactDown(object sender, ContactEventArgs e)
{
    MyUserControl uc = (MyUserControl) sender;

    Point position = e.GetPosition(uc);
    Double orientation = e.Contact.GetOrientation(uc);

    Debug.WriteLine("El contacto se ha producido en la posición: {0}, {1}.", position.X, position.Y);
    Debug.WriteLine("La orientación del contacto es de {0} grados.", orientation);

    if (e.Contact.IsFingerRecognized)
    {
        Debug.WriteLine("Es un dedo.");
    }
    else if (e.Contact.IsTagRecognized)
    {
        Debug.WriteLine("Es un elemento etiquetado.");

        switch (e.Contact.Tag.Type)
        {
            case TagType.Byte:

                Byte byteTagValue = e.Contact.Tag.Byte.Value;

                Debug.WriteLine("Es un Byte Tag. Su valor es {0}.", byteTagValue);
                break;

            case TagType.Identity:

                long serie = e.Contact.Tag.Identity.Series;
                long identityTagValue = e.Contact.Tag.Identity.Value;

                Debug.WriteLine("Es un Identity Tag. Su serie es: {0}. Su valor es {1}.", serie, identityTagValue);
                break;
        }
    }
    else
    {
        Debug.WriteLine("Es un objeto.");
    }
}</pre>
<p>Por último, si el contacto es un objeto cualquiera, nos interesará saber su forma y el área que ocupa. El propio SDK nos ayuda creando un objeto <em>Ellipse</em> que tiene la forma aproximada del contacto. Nosotros podemos saber dónde está el centro del elipse, cuál es su tamaño y incluso el área exacta del objeto que toca la pantalla. Debemos observar los métodos <em>e.Contact.GetEllipse</em>,  <em>e.Contact.GetCenterPosition</em>, y la propiedad <em>e.Contact.PhysicalArea</em>. Los métodos para obtener los valores de la elipse también reciben por parámetro el objeto respecto al que deben calcularse. Igual que antes, lo normal sería usar el parámetro <em>sender</em>.</p>
<pre class="brush:csharp">private void SurfaceUserControl_ContactDown(object sender, ContactEventArgs e)
{
    MyUserControl uc = (MyUserControl) sender;

    Point position = e.GetPosition(uc);
    Double orientation = e.Contact.GetOrientation(uc);

    Debug.WriteLine("El contacto se ha producido en la posición: {0}, {1}.", position.X, position.Y);
    Debug.WriteLine("La orientación del contacto es de {0} grados.", orientation);

    if (e.Contact.IsFingerRecognized)
    {
        Debug.WriteLine("Es un dedo.");
    }
    else if (e.Contact.IsTagRecognized)
    {
        Debug.WriteLine("Es un elemento etiquetado.");

        switch (e.Contact.Tag.Type)
        {
            case TagType.Byte:

                Byte byteTagValue = e.Contact.Tag.Byte.Value;

                Debug.WriteLine("Es un Byte Tag. Su valor es {0}.", byteTagValue);
                break;

            case TagType.Identity:

                long serie = e.Contact.Tag.Identity.Series;
                long identityTagValue = e.Contact.Tag.Identity.Value;

                Debug.WriteLine("Es un Identity Tag. Su serie es: {0}. Su valor es {1}.", serie, identityTagValue);
                break;
        }
    }
    else
    {
        Double area = e.Contact.PhysicalArea;
        Ellipse ellipse = e.Contact.GetEllipse(uc);
        Point ellipseCenter = e.Contact.GetCenterPosition(uc);

        Debug.WriteLine("Es un objeto.");
        Debug.WriteLine("La elipse aproximada que contiene el contacto es ancho: {0}, alto: {1}", ellipse.Width, ellipse.Height);
        Debug.WriteLine("El punto central de la elipse es: {0}, {1}", ellipseCenter.X, ellipseCenter.Y);
    }
}</pre>
<h3>Reconocer el mismo contacto en diferentes eventos.</h3>
<p>Los contactos en realidad disparan más de un evento. Por ejemplo, un mismo contacto primero genera un &#8220;<em>ContactDown</em>&#8221; y por último generará un &#8220;<em>ContactUp</em>&#8220;. Entonces, ¿Cómo saber que son el mismo?. Para ello usaremos la propiedad<em> e.Contact.Id</em>. El mismo contacto, en diferentes eventos; conservará el mismo Id.</p>
<h3>Conocer los diferentes contactos sobre un elemento.</h3>
<p>Y para acabar, algo que también nos puede ser de utilidad es conocer los diferentes contactos que hay sobre un elemento. Para ello, podemos usar la propiedad <em>ContactsOver</em> que nos proporcionan los controles de usuario. Esto es una lista de objetos <em>Contact</em>, por lo que a cada elemento se le podrían aplicar todas las propiedades y métodos vistos en este artículo.</p>
<h3>Hemos acabado.</h3>
<p>Bueno, acabamos de pegar un buen repaso a los contactos de Surface. Dejo la descarga a un ejemplo que desarrollé para escribir este artículo.</p>
<p><a href="http://www.juanmasantoyo.es/wp-content/uploads/2010/09/DeteccionDeContactos.zip">Deteccion de contactos (VS 2010)</a></p>
<p>El contenido de este artículo debería ser suficiente para que cualquier hombre de bien desarrolle aplicaciones bastante decentes para Microsoft Surface, pero el que tenga dudas o necesite más información sobre algún aspecto que no dude en comentarlo por aquí. Yo mismo sigo aprendiendo sobre el tema, así que cualquier ayuda que os pueda prestar también me ayuda a mí.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.juanmasantoyo.es/index.php/2010/09/22/deteccion-y-gestion-de-contactos-en-una-surface/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Navegador basado en Chromium para integrar en aplicaciones WPF</title>
		<link>http://www.juanmasantoyo.es/index.php/2010/09/03/navegador-basado-en-chromium-para-integrar-en-aplicaciones-wpf/</link>
		<comments>http://www.juanmasantoyo.es/index.php/2010/09/03/navegador-basado-en-chromium-para-integrar-en-aplicaciones-wpf/#comments</comments>
		<pubDate>Fri, 03 Sep 2010 18:32:53 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[surface]]></category>

		<guid isPermaLink="false">http://www.juanmasantoyo.es/?p=504</guid>
		<description><![CDATA[Desde hace semanas, intento encontrar la manera de identificar un usuario en Facebook desde una aplicación de Surface (WPF)&#8230; sin mucho éxito por el momento (de conseguir algo, será seguro una gran guarrería, que por supuesto publicaré en el blog). &#8230; <a href="http://www.juanmasantoyo.es/index.php/2010/09/03/navegador-basado-en-chromium-para-integrar-en-aplicaciones-wpf/">Seguir leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Desde hace semanas, intento encontrar la manera de identificar un usuario en Facebook desde una aplicación de Surface (WPF)&#8230; sin mucho éxito por el momento (de conseguir algo, será seguro una gran guarrería, que por supuesto publicaré en el blog).</p>
<p>No obstante, hice algunas preguntas por el blog de desarrolladores de Surface en MSDN USA, y es ahí donde me recomendaron este navegador para integrar en aplicaciones WPF:</p>
<p><a href="http://chriscavanagh.wordpress.com/2009/08/25/a-real-wpf-webbrowser/">http://chriscavanagh.wordpress.com/2009/08/25/a-real-wpf-webbrowser/</a></p>
<p>El proyecto es muy interesante: han aprovechado que el código de Chromium es libre para hacer una adaptación del mismo en WPF. Para que quede más claro, estoy hablando de un control de usuario 100% funcional, que puede ser integrado en aplicaciones WPF y que es una alternativa al control WebBrowser (el problema de este es que no es más que el Internet Explorer integrado en la aplicación).</p>
<p>En realidad este navegador no es exáctamente lo que necesito para mi aplicación y no lo he probado, pero como después de semanas de investigación esto es lo más interesante que me he encontrado, quería comentarlo.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.juanmasantoyo.es/index.php/2010/09/03/navegador-basado-en-chromium-para-integrar-en-aplicaciones-wpf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introducción al componente ScatterView de Surface (2: ScatterViews con C#)</title>
		<link>http://www.juanmasantoyo.es/index.php/2010/08/03/introduccion-al-componente-scatterview-de-surface-parte-2/</link>
		<comments>http://www.juanmasantoyo.es/index.php/2010/08/03/introduccion-al-componente-scatterview-de-surface-parte-2/#comments</comments>
		<pubDate>Tue, 03 Aug 2010 05:27:06 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[surface]]></category>
		<category><![CDATA[scatterview]]></category>

		<guid isPermaLink="false">http://www.juanmasantoyo.es/?p=352</guid>
		<description><![CDATA[Ya hemos visto como podemos usar los ScatterView a base de XAML, pero muchas veces vamos a tener la necesidad de tratarlos desde C#. En este artículo, veremos cómo podemos trabajar con ScatterViews de forma dinámica. Preparamos el proyecto Antes &#8230; <a href="http://www.juanmasantoyo.es/index.php/2010/08/03/introduccion-al-componente-scatterview-de-surface-parte-2/">Seguir leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Ya hemos visto como podemos <a href="http://www.juanmasantoyo.es/index.php/2010/04/08/introduccion-al-componente-scatterview-de-surface-parte-1/">usar los <em>ScatterView</em> a base de <em>XAML</em></a>, pero muchas veces vamos a tener la necesidad de tratarlos desde <em>C#</em>.</p>
<p>En este artículo, veremos cómo podemos trabajar con ScatterViews de forma dinámica.<br />
<span id="more-352"></span></p>
<h3>Preparamos el proyecto</h3>
<p>Antes de iniciar el Visual Studio, debemos haber iniciado el emulador de Surface que viene con el <em>SDK</em>. Si no lo has hecho así, cierra el Visual Studio y inícialo todo en el orden correcto.</p>
<p>Usaremos el proyecto <em>HelloScatterView</em> que creamos en el primer artículo, y crearemos una nueva ventana <em>XAML</em> llamada &#8220;<em>CSharpSample</em>&#8220;. Tendremos que modificar el archivo <em>App.xml</em> (atrubito <em>StartupUri</em>) para que inicie la aplicación en la nueva ventana.</p>
<h3>ScatterViews simples con C#</h3>
<p>Vamos a considerar un <em>XAML</em> muy básico, sin <em>ScatterViewItems</em>. Sí que vamos a añadir tres botones que nos proporcionarán un mínimo de funcionalidad.</p>
<pre class="brush:xml">
	&lt;s:SurfaceWindow
		x:Class=&quot;HelloScatterView.SurfaceWindow1&quot;
		xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
		xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
		xmlns:s=&quot;http://schemas.microsoft.com/surface/2008&quot;
		Title=&quot;HelloScatterView&quot;&gt;

		&lt;s:SurfaceWindow.Resources&gt;
			&lt;ImageBrush x:Key=&quot;WindowBackground&quot;
					  Stretch=&quot;None&quot; Opacity=&quot;0.6&quot;
					  ImageSource=&quot;pack://application:,,,/Resources/WindowBackground.jpg&quot;/&gt;
		&lt;/s:SurfaceWindow.Resources&gt;

		&lt;DockPanel&gt;
			&lt;UniformGrid Background=&quot;Black&quot; Height=&quot;50&quot; DockPanel.Dock=&quot;Top&quot; Columns=&quot;3&quot;&gt;
				&lt;s:SurfaceButton Content=&quot;Add&quot; Click=&quot;Add&quot; Foreground=&quot;White&quot;/&gt;
				&lt;s:SurfaceButton Content=&quot;Remove&quot; Click=&quot;Remove&quot; Foreground=&quot;White&quot;/&gt;
				&lt;s:SurfaceButton Content=&quot;Clear&quot; Click=&quot;Clear&quot; Foreground=&quot;White&quot;/&gt;
			&lt;/UniformGrid&gt;
			&lt;s:ScatterView x:Name=&quot;Scatter&quot;/&gt;
		&lt;/DockPanel&gt;
	&lt;/s:SurfaceWindow&gt;
</pre>
<p>Por ahora esto es todo el <em>XAML</em> que vamos a usar. La parte importante del código, la hacemos desde <em>C#</em>, en el archivo <em>CSharpSample.xaml.cs</em>.</p>
<p>Antes de continuar vamos a dejar claro que hará cada botón:</p>
<ul>
<li>El botón Add añadirá un <em>ScatterViewItem</em> con una de las imágenes (se seguirá un orden cíclico).</li>
<li>El botón Remove quitará el último <em>ScatterViewItem</em> añadido.</li>
<li>El botón Clear quitará todos los <em>ScatterViewItems</em>.</li>
</ul>
<h4>Inicializamos</h4>
<p>Creamos en el <em>.cs</em> una propiedad global que será una lista con los nombres de las imágenes, y otra propiedad que será un <em>String</em> con la ruta del directorio que las contiene, de forma que al concatenar el directorio con nombre de imagen tengamos la ruta completa. Daremos los correspondientes valores a ambas propiedades.</p>
<pre class="brush:csharp">
namespace HelloScatterView
{
    public partial class CSharpSample : SurfaceWindow
    {
        string folder = string.Empty;
        List&lt;string&gt; images = new List&lt;string&gt;();

        public CSharpSample()
        {
            this.folder = &quot;Resources/Img/&quot;;

            images.Add(&quot;fuente_tres_chorros.jpg&quot;);
            images.Add(&quot;kiyoumizu_dera.jpg&quot;);
            images.Add(&quot;laputa_robot.jpg&quot;);

            InitializeComponent();

            // Add handlers for Application activation events
            AddActivationHandlers();
        }
	}
}
</pre>
<h4>Eventos de los botones</h4>
<p>El evento click del botón añadir creará un ScatterViewItem, le asignará la imagen y lo añadirá al contenedor ScatterView. Para saber que imagen añadir, se basará en el total de imágenes añadidas.</p>
<pre class="brush:csharp">
private void Add(object sender, RoutedEventArgs e)
{
	// Calculamos el indice de la imagen a mostrar en función de la cantidad de elementos en el ScatterView
	int index = this.Scatter.Items.Count % this.images.Count;

	// Creamos el ScatterViewItem que vamos a añadir
	BitmapImage bmp = new BitmapImage(new Uri(this.folder + this.images[index], UriKind.Relative));
	Image img = new Image();
	img.Source = bmp;

	ScatterViewItem svi = new ScatterViewItem();
	svi.Content = img;

	Scatter.Items.Add(svi);
}
</pre>
<p>El evento click del botón eliminar, accederá a la última imagen añadida en el contenedor ScatterView y la eliminará:</p>
<pre class="brush:csharp">
private void Remove(object sender, RoutedEventArgs e)
{
	// Averiguamos el índice del último elemento añadido
	int index = this.Scatter.Items.Count - 1;

	if (index &gt;= 0)
	{
		this.Scatter.Items.Remove(this.Scatter.Items[index]);
	}
}
</pre>
<p>El evento click del botón borrar limpiará complétamente el contenedor ScatterView:</p>
<pre class="brush:csharp">
private void Clear(object sender, RoutedEventArgs e)
{
	this.Scatter.Items.Clear();
}
</pre>
<h3>Añadir ScatterViews con Data Binding</h3>
<p>Pero vamos a aprovechar las características de <em>.Net</em> para añadir los ScatterViewItems de una forma más potente. En realidad, podemos definir un origen de datos de forma que <em>.Net</em> añadirá todas las imágenes que contenga al contenedor ScatterView.</p>
<p>Dicho de otra forma, en pocas líneas de código podemos conseguir añadir al ScatterView todas las imágenes que haya, por ejemplo; en un directorio determinado. Vamos a hacer un ajuste en el constructor de CSharpSample y en el nodo s:ScatterView del XAML:</p>
<h4>En el C#</h4>
<pre class="brush:csharp">
public CSharpSample()
{
	this.folder = &quot;Resources/Img/&quot;;

	images.Add(&quot;fuente_tres_chorros.jpg&quot;);
	images.Add(&quot;kiyoumizu_dera.jpg&quot;);
	images.Add(&quot;laputa_robot.jpg&quot;);

	InitializeComponent();

	// Add handlers for Application activation events
	AddActivationHandlers();

	String[] files = System.IO.Directory.GetFiles(&quot;Resources/Img&quot;, &quot;*.jpg&quot;);
	this.Scatter.ItemsSource = files;
}
</pre>
<p>Lo importante son las últimas lineas: obtienen la lista de imágenes en un directorio y la establecen como el origen de datos del ScatterView.</p>
<h4>En el XAML#</h4>
<pre class="brush:xml">
&lt;s:ScatterView x:Name=&quot;Scatter&quot;&gt;
	&lt;s:ScatterView.ItemTemplate&gt;
		&lt;DataTemplate&gt;
			&lt;s:ScatterViewItem&gt;
				&lt;Image Source=&quot;{Binding}&quot; /&gt;
			&lt;/s:ScatterViewItem&gt;
		&lt;/DataTemplate&gt;
	&lt;/s:ScatterView.ItemTemplate&gt;
&lt;/s:ScatterView&gt;
</pre>
<p>Lo importante es el nodo ItemTemplate: hemos establecido una plantilla que es la que usarán los elementos en el origen de datos.</p>
<h3>Es todo por hoy</h3>
<p>Ahora ya sabemos crear ScatterVirews desde <em>XAML</em> y desde C#, pero esto es sólo el principio. Como comenté en el primer artículo, un ScatterViewItem es mucho más que una imagen; y eso es lo que veremos en el próximo artículo sobre ScatterViews.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.juanmasantoyo.es/index.php/2010/08/03/introduccion-al-componente-scatterview-de-surface-parte-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Animar transformaciones en WPF con el método BeginAnimation</title>
		<link>http://www.juanmasantoyo.es/index.php/2010/07/06/animar-transformaciones-en-wpf-con-el-metodo-beginanimation/</link>
		<comments>http://www.juanmasantoyo.es/index.php/2010/07/06/animar-transformaciones-en-wpf-con-el-metodo-beginanimation/#comments</comments>
		<pubDate>Tue, 06 Jul 2010 22:17:31 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[surface]]></category>

		<guid isPermaLink="false">http://www.juanmasantoyo.es/?p=475</guid>
		<description><![CDATA[Me preguntaron hace poco cómo animar elementos en Microsoft Surface. En esencia se haría como en cualquier entorno basado en WPF. Hay varias formas de animar, pero quizás una de las más sencilla y potente sea la animación de transformaciones &#8230; <a href="http://www.juanmasantoyo.es/index.php/2010/07/06/animar-transformaciones-en-wpf-con-el-metodo-beginanimation/">Seguir leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Me preguntaron hace poco cómo animar elementos en Microsoft Surface. En esencia se haría como en cualquier entorno basado en WPF.</p>
<p>Hay varias formas de animar, pero quizás una de las más sencilla y potente sea la animación de transformaciones con el método <em>BeginAnimation</em>.<br />
<span id="more-475"></span></p>
<h3>Las transformaciones.</h3>
<p>En WPF existen varios tipos de transformaciones:</p>
<ul>
<li><em><a href="http://msdn.microsoft.com/es-es/library/system.windows.media.rotatetransform.aspx">RotateTransform</a></em>. Cambia la orientación de un elemento.</li>
<li><em><a href="http://msdn.microsoft.com/es-es/library/system.windows.media.scaletransform.aspx">ScaleTransform</a></em>. Cambia el tamaño de un elemento.</li>
<li><em><a href="http://msdn.microsoft.com/es-es/library/system.windows.media.translatetransform.aspx">TranslateTransform</a></em>. Cambia la posición de un elemento.</li>
<li><em><a href="http://msdn.microsoft.com/es-es/library/system.windows.media.transformgroup.aspx">TransformGroup</a></em>. Es un tipo de transformación especial, ya que consiste en una combinación de las tres anteriores.</li>
</ul>
<h3>Animar transformaciones.</h3>
<p>La idea es simple: Una animación consiste en modificar progresivamente el valor de una propiedad durante un periodo de tiempo. En principio, se puede animar cualquier propiedad de dependencia del API de WPF.</p>
<p>Concretamente, las transformaciones usan propiedades de dependencia para modificar el aspecto del elemento en el que se aplican; así que si aplicamos una animación sobre una propiedad de una transformación de cualquier tipo, el resultado será una animación sobre el elemento.</p>
<p>El código para aplicar una transformación es sencillo. Se puede aplicar desde XAML o desde C#, pero en lo personal prefiero hacerlo en XAML:</p>
<pre class="brush:xml">	&lt;Image x:Name="MyImage" Source="images/myimage.png" Width="100" Height="100"&gt;
		&lt;Image.RenderTransform&gt;
			&lt;TransformGroup&gt;
				&lt;TranslateTransform x:Name="Translacion" X="85" /&gt;
				&lt;RotateTransform x:Name="Rotacion" Angle="0" CenterX="15" CenterY="15" /&gt;
			&lt;/TransformGroup&gt;
		&lt;/Image.RenderTransform&gt;
	&lt;/Image&gt;</pre>
<p>Fijaos que al usar el nodo <em>&#8220;TransformGroup&#8221;</em> podemos aplicar más de una transformación. De no usarlo sólo podríamos aplicar una, ya que el nodo <em>&#8220;Image.RenderTransform&#8221;</em> sólo admite un nodo hijo. Notad también que las transformaciones se aplican desde la última a la primera. No es lo mismo mover y rotar, que rotar y mover.</p>
<h3>Las animaciones y el método BeginAnimation.</h3>
<p>A nivel práctico, una animación es un objeto con una serie de propiedades configuradas, como por ejemplo la duración de la animación, la aceleración, el valor inicial y final de la propiedad, etc. Dependiendo del tipo de dato que queramos animar, el objeto de animación cambia. No es lo mismo animar un color (<em>ColorAnimation</em>) que una orientación (<em>DoubleAnimation</em>). Se pueden ver todos los tipos de animación posible en la especificación de la clase madre: <em><a href="http://msdn.microsoft.com/es-es/library/system.windows.media.animation.animationtimeline.aspx">AnimationTimeLine</a></em>.</p>
<p>Para aplicar una animación sobre una transformación, contamos con un potente aliado: el método <em>BeginAnimation</em>, presente en todas las transformaciones. Al método <em>BeginAnimation</em> se le pasan dos parámetros: la propiedad de dependencia a animar, y la animación. La animación deberemos construirla en base a lo que queremos animar, la propiedad de dependencia es una propiedad estática de la clase a la que pertenece el elemento que queremos animar. Por ejemplo, si queremos animar el ángulo de un <em>RotateTransform</em>, tendremos una propiedad estática &#8220;<em>RotateTransform.AngleProperty</em>&#8220;. Más fácil con un poco de código C#:</p>
<pre class="brush:csharp">	DoubleAnimation animacion = new DoubleAnimation();

	animacion.To = 180;
	animacion.Duration = new Duration(TimeSpan.FromMilliseconds(1000));

	Rotacion.BeginAnimation(RotateTransform.AngleProperty, animacion);</pre>
<h3>Es todo por el momento.</h3>
<p>Y en realidad no hay mucho más que decir sobre animaciones. Sólo destacar que, como imagináis, el objeto animación tiene eventos que informarán del estado del proceso, y que no son bloqueantes (es decir, mientras una animación se ejecuta, el flujo del programa no se detiene, por lo que necesitan una gestión asíncrona). También destacar que la animación se iniciará en el instante en que se ejecute el método <em>BeginAnimation</em>.</p>
<p>Si queréis aprender sobre animaciones más complejas, os recomiendo que miréis el objeto <em><a href="http://msdn.microsoft.com/en-us/library/system.windows.media.animation.storyboard.aspx">StoryBoard</a></em>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.juanmasantoyo.es/index.php/2010/07/06/animar-transformaciones-en-wpf-con-el-metodo-beginanimation/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Vídeo de Rent a Car Surface by Bizzit</title>
		<link>http://www.juanmasantoyo.es/index.php/2010/07/06/video-de-rent-a-car-surface-by-bizzit/</link>
		<comments>http://www.juanmasantoyo.es/index.php/2010/07/06/video-de-rent-a-car-surface-by-bizzit/#comments</comments>
		<pubDate>Tue, 06 Jul 2010 21:28:47 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[surface]]></category>

		<guid isPermaLink="false">http://www.juanmasantoyo.es/?p=463</guid>
		<description><![CDATA[Ya he hablado en mi blog algúna vez sobre la demo para Microsoft Surface que estábamos realizando en Bizzit. La aplicación fue principalmente desarrollada por un servidor (me refiero al que escribe, no a un servidor de aplicaciones ), y &#8230; <a href="http://www.juanmasantoyo.es/index.php/2010/07/06/video-de-rent-a-car-surface-by-bizzit/">Seguir leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Ya he hablado en mi blog algúna vez sobre la demo para Microsoft Surface que estábamos realizando en Bizzit.</p>
<p>La aplicación fue principalmente desarrollada por un servidor (me refiero al que escribe, no a un servidor de aplicaciones <img src='http://www.juanmasantoyo.es/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ), y fue un reto muy bonito. La verdad es que ha sido una experiencia profesional muy interesante y divertida.</p>
<p>Bueno, al tema: Mi compañero en esta aventura, Carlos García; ha realizado un vídeo donde se puede ver cómo es la aplicación y su funcionamiento. Me llena de orgullo y satisfacción compartirlo con todos vosotros:</p>
<div style="text-align: center;"><object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/ax-0BToUTGo" /><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><embed wmode="opaque" src="http://www.youtube.com/v/ax-0BToUTGo" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></div>
]]></content:encoded>
			<wfw:commentRss>http://www.juanmasantoyo.es/index.php/2010/07/06/video-de-rent-a-car-surface-by-bizzit/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Charla sobre Microsoft Surface</title>
		<link>http://www.juanmasantoyo.es/index.php/2010/05/28/charla-sobre-microsoft-surface/</link>
		<comments>http://www.juanmasantoyo.es/index.php/2010/05/28/charla-sobre-microsoft-surface/#comments</comments>
		<pubDate>Fri, 28 May 2010 15:15:12 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[surface]]></category>

		<guid isPermaLink="false">http://www.juanmasantoyo.es/?p=455</guid>
		<description><![CDATA[Ayer dí una charla sobre Microsoft Surface en el centro de Innovación de Microsoft de Palma para el grupo de desarrolladores de .Net en Baleares. Hablamos un poco de todo lo que implica la Surface y el desarrollo de aplicaciones &#8230; <a href="http://www.juanmasantoyo.es/index.php/2010/05/28/charla-sobre-microsoft-surface/">Seguir leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Ayer dí una charla sobre Microsoft Surface en el centro de Innovación de Microsoft de Palma para el grupo de desarrolladores de .Net en Baleares.</p>
<p>Hablamos un poco de todo lo que implica la Surface y el desarrollo de aplicaciones para este dispositivo. Fue una experiencia muy gratificante.</p>
<p>Dejo la descarga del Power Point que redacté para la ocasión, por si os interesa.</p>
<p><a href='http://www.juanmasantoyo.es/wp-content/uploads/2010/05/Microsoft-Surface.zip'>Microsoft Surface</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.juanmasantoyo.es/index.php/2010/05/28/charla-sobre-microsoft-surface/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>ScatterViewItem invisibles en Microsoft Surface</title>
		<link>http://www.juanmasantoyo.es/index.php/2010/05/18/scatterviewitem-invisibles-en-microsoft-surface/</link>
		<comments>http://www.juanmasantoyo.es/index.php/2010/05/18/scatterviewitem-invisibles-en-microsoft-surface/#comments</comments>
		<pubDate>Tue, 18 May 2010 06:00:57 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[surface]]></category>
		<category><![CDATA[scatterviewitem invisible]]></category>

		<guid isPermaLink="false">http://www.juanmasantoyo.es/?p=449</guid>
		<description><![CDATA[Cuando empecé a desarrollar para Microsoft Surface, me di cuenta de tres cosas: El control ScatterViewItem es la base de toda aplicación. La mayoría de las veces, no queremos que el ScatterViewItem tenga la apariencia tan horrible que tiene por &#8230; <a href="http://www.juanmasantoyo.es/index.php/2010/05/18/scatterviewitem-invisibles-en-microsoft-surface/">Seguir leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Cuando empecé a desarrollar para Microsoft Surface, me di cuenta de tres cosas:</p>
<ol>
<li>El control ScatterViewItem es la base de toda aplicación.</li>
<li>La mayoría de las veces, no queremos que el ScatterViewItem tenga la apariencia tan horrible que tiene por defecto, es más, nos interesará que sea &#8220;invisible&#8221;.</li>
<li>El control ScatterViewItem no proporciona ningun sistema simple para volverse invisible.</li>
</ol>
<p>Así que despues de trastear un poco con Microsoft Expression Blend, conseguí montar un pequeño estilo que podemos aplicar a nuestros ScatterViewItem para que estos sean invisibles. Esto es, inapreciables para el usuario. Por lo tanto, el contenido se verá perfectamente, pero las sombras, reflejos, destellos y demás tonterías, no.<br />
<span id="more-449"></span><br />
Este es el estilo en cuestión:</p>
<pre class="brush:xml">
&lt;Style x:Key=&quot;InvisibleScatterViewItem&quot; TargetType=&quot;{x:Type s:ScatterViewItem}&quot;&gt;
    &lt;Setter Property=&quot;Template&quot;&gt;
        &lt;Setter.Value&gt;
            &lt;ControlTemplate TargetType=&quot;{x:Type s:ScatterViewItem}&quot;&gt;
                &lt;ContentPresenter /&gt;
            &lt;/ControlTemplate&gt;
        &lt;/Setter.Value&gt;
    &lt;/Setter&gt;
&lt;/Style&gt;
</pre>
<p>Espero que os sirva tanto como a mí.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.juanmasantoyo.es/index.php/2010/05/18/scatterviewitem-invisibles-en-microsoft-surface/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Introducción al componente ScatterView de Surface (1: ScatterViews con XAML)</title>
		<link>http://www.juanmasantoyo.es/index.php/2010/04/08/introduccion-al-componente-scatterview-de-surface-parte-1/</link>
		<comments>http://www.juanmasantoyo.es/index.php/2010/04/08/introduccion-al-componente-scatterview-de-surface-parte-1/#comments</comments>
		<pubDate>Thu, 08 Apr 2010 12:30:16 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[surface]]></category>
		<category><![CDATA[scatterview]]></category>

		<guid isPermaLink="false">http://www.juanmasantoyo.es/?p=332</guid>
		<description><![CDATA[El multitouch es probablemente una de las características más atractivas de Surface. Esto se debe a que plantea una serie de posibilidades al usuario que convierte su experiencia en algo mucho más intuitivo y sencillo. El componente ScatterView es quizás &#8230; <a href="http://www.juanmasantoyo.es/index.php/2010/04/08/introduccion-al-componente-scatterview-de-surface-parte-1/">Seguir leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>El multitouch es probablemente una de las características más atractivas de Surface. Esto se debe a que plantea una serie de posibilidades al usuario que convierte su experiencia en algo mucho más intuitivo y sencillo.</p>
<p>El componente <em>ScatterView</em> es quizás uno de los mejores ejemplos de esto. Este es el primero de varios artículos en el que veremos cómo se usan y qué posiblides nos ofrecen.<br />
<span id="more-332"></span></p>
<h3>Sobre el componente <em>ScatterView</em></h3>
<p>Un <em>ScatterView</em> representa un elemento que reacciona a los contactos sobre Surface y que se puede mover, rotar o redimensionar.</p>
<p>El ejemplo más clásico sería un puñado de fotografías. Cada una de esas fotografías puede ser un <em>ScatterView</em>.</p>
<h3>Preparamos el proyecto</h3>
<p>Antes de iniciar el Visual Studio, debemos haber iniciado el emulador de Surface que viene con el SDK. Si no lo has hecho así, cierra el Visual Studio y inícialo todo en el orden correcto.</p>
<h4>Creamos el proyecto</h4>
<p>Nuestro proyecto va a ser una aplicación para Surface basada en WPF. Lo llamaremos HelloScatterView.</p>
<p>Al crear nuestro proyecto se nos ha creado una ventana por defecto: SurfaceWindow1. La renombraremos, y le pondremos el nombre de &#8220;<strong>XamlSample</strong>&#8220;.</p>
<h4>Añadimos unas imágenes</h4>
<p>Para poder trabajar con los <strong>ScatterViews</strong>, necesitaremos algunas imágenes.</p>
<p>Dentro de nuestro proyecto Surface tenemos una carpeta llamada Resources. Crearemos otra carpeta en su interior llamada Img y ubicaremos ahí nuestras imágenes.</p>
<h3>Añadir <em>ScatterViews</em> desde XAML</h3>
<h4><em>ScatterView</em> simple con XAML</h4>
<p>Comenzaremos usando los <em>ScatterViews</em> desde XAML. En realidad añadir un <em>ScatterView</em> es muy simple:</p>
<pre class="brush:xml">
&lt;s:ScatterView&gt;
    &lt;Image Source=&quot;Resources/Img/fuente_tres_chorros.jpg&quot;/&gt;
&lt;/s:ScatterView&gt;
</pre>
<p><img src="http://www.juanmasantoyo.es/wp-content/uploads/2010/02/01-300x225.jpg" alt="" title="Ejemplo de ScatterView" width="300" height="225" class="aligncenter size-medium wp-image-333" /></p>
<p>Este es el código que añade un <em>ScatterView</em>. Fijaos en un detalle: añadir un <em>ScatterView</em> no es sólo añadir el nodo <em>ScatterView</em>, también es añadir el recurso que se manejará, en este caso la imagen. Y es que un <em>ScatterView</em> no es una imagen, sino la capacidad que tiene un elemento (en este caso una imagen) de ser rotado, redimensionado y movido.</p>
<p>El XAML completo de la ventana es este:</p>
<pre class="brush:xml">
&lt;s:SurfaceWindow
    x:Class=&quot;HelloScatterView.SurfaceWindow1&quot;
    xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
    xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
    xmlns:s=&quot;http://schemas.microsoft.com/surface/2008&quot;
    Title=&quot;HelloScatterView&quot;&gt;
    &lt;s:SurfaceWindow.Resources&gt;
        &lt;ImageBrush x:Key=&quot;WindowBackground&quot;
                  Stretch=&quot;None&quot; Opacity=&quot;0.6&quot;
                  ImageSource=&quot;pack://application:,,,/Resources/WindowBackground.jpg&quot;/&gt;
    &lt;/s:SurfaceWindow.Resources&gt;
    &lt;s:ScatterView&gt;
        &lt;Image Source=&quot;Resources/Img/fuente_tres_chorros.jpg&quot;/&gt;
    &lt;/s:ScatterView&gt;
&lt;/s:SurfaceWindow&gt;
</pre>
<p>Si ahora compilamos nuestro proyecto, podremos jugar un poco con nuestra foto sobre el emulador de Surface. Incluso, si conectas dos ratones por USB puedes simular multitouch.</p>
<p>Vamos a hacerlo un poco más espectacular añadiendo varias imágenes:</p>
<pre class="brush:xml">
&lt;s:ScatterView&gt;
    &lt;Image Source=&quot;Resources/Img/fuente_tres_chorros.jpg&quot;/&gt;
    &lt;Image Source=&quot;Resources/Img/kiyoumizu_dera.jpg&quot;/&gt;
    &lt;Image Source=&quot;Resources/Img/laputa_robot.jpg&quot;/&gt;
    &lt;Image Source=&quot;Resources/Img/fuente_tres_chorros.jpg&quot;/&gt;
    &lt;Image Source=&quot;Resources/Img/kiyoumizu_dera.jpg&quot;/&gt;
    &lt;Image Source=&quot;Resources/Img/laputa_robot.jpg&quot;/&gt;
&lt;/s:ScatterView&gt;
</pre>
<p><img src="http://www.juanmasantoyo.es/wp-content/uploads/2010/02/02-300x225.jpg" alt="" title="Ejemplo de varios ScatterViews" width="300" height="225" class="aligncenter size-medium wp-image-334" /></p>
<h4><em>Scatterviews</em> complejos con XAML</h4>
<p>Probablemente ya te estés preguntando lo siguiente: ¿cómo determinar los parámetros por defecto de nuestro <em>ScatterView</em>? Vamos a ello.</p>
<p>La clave está en que la estructura que hemos usado ahora no acaba de ser la mejor. En realidad, nos está faltando crear un <em>ScatterViewItem</em>, que hasta el momento se estaba creando de forma automática para cada elemento en el <em>ScatterView</em>.</p>
<pre class="brush:xml">
&lt;s:ScatterView&gt;
	&lt;s:ScatterViewItem&gt;
		&lt;Image Source=&quot;Resources/Img/fuente_tres_chorros.jpg&quot;/&gt;
	&lt;/s:ScatterViewItem&gt;
&lt;/s:ScatterView&gt;
</pre>
<p>En el nodo <em>ScatterViewItem</em> podemos establecer muchas propiedades que afectarán al comportamiento de nuestro <em>ScatterView</em>.</p>
<p>Algunas de esas propiedades son:</p>
<ul>
<li><strong>MinWidth</strong>, <strong>MaxWidth</strong>, <strong>MinHeight</strong>, <strong>MaxHeight</strong>: Máximos y mínimos de anchura y altura.</li>
<li><strong>CanMove</strong>, <strong>CanRotate</strong>, <strong>CanScale</strong>: Activan o desactivan las capacidades de mover, rotar y redimensionar.</li>
<li><strong>Width</strong>, <strong>Height</strong>, <strong>Center</strong>, <strong>Orientation</strong>: Valores iniciales para el ancho, el alto, la posición, y la rotación.</li>
<li><strong>BorderBrush</strong>, <strong>BorderThikness</strong>: Color y grosor del borde.</li>
</ul>
<p>Un ejemplo sencillo:</p>
<pre class="brush:xml">
&lt;s:ScatterView&gt;
	&lt;s:ScatterViewItem Center=&quot;512,384&quot; Orientation=&quot;0&quot;&gt;
		&lt;Image Source=&quot;Resources/Img/fuente_tres_chorros.jpg&quot;/&gt;
	&lt;/s:ScatterViewItem&gt;

	&lt;s:ScatterViewItem Center=&quot;512,384&quot; Orientation=&quot;60&quot;&gt;
		&lt;Image Source=&quot;Resources/Img/kiyoumizu_dera.jpg&quot;/&gt;
	&lt;/s:ScatterViewItem&gt;

	&lt;s:ScatterViewItem Center=&quot;512,384&quot; Orientation=&quot;180&quot;&gt;
		&lt;Image Source=&quot;Resources/Img/laputa_robot.jpg&quot;/&gt;
	&lt;/s:ScatterViewItem&gt;

	&lt;s:ScatterViewItem Center=&quot;512,384&quot; Orientation=&quot;240&quot;&gt;
		&lt;Image Source=&quot;Resources/Img/fuente_tres_chorros.jpg&quot;/&gt;
	&lt;/s:ScatterViewItem&gt;

	&lt;s:ScatterViewItem Center=&quot;512,384&quot; Orientation=&quot;300&quot;&gt;
		&lt;Image Source=&quot;Resources/Img/kiyoumizu_dera.jpg&quot;/&gt;
	&lt;/s:ScatterViewItem&gt;

	&lt;s:ScatterViewItem Center=&quot;512,384&quot; Orientation=&quot;360&quot;&gt;
		&lt;Image Source=&quot;Resources/Img/laputa_robot.jpg&quot;/&gt;
	&lt;/s:ScatterViewItem&gt;
&lt;/s:ScatterView&gt;
</pre>
<p>Aunque de hecho, podemos centralizar la mayoría de estas propiedades en un único nodo, como un estilo:</p>
<pre class="brush:xml">
&lt;s:ScatterView&gt;
	&lt;s:ScatterView.ItemContainerStyle&gt;
		&lt;Style TargetType=&quot;{x:Type s:ScatterViewItem}&quot;&gt;
			&lt;Setter Property=&quot;Center&quot; Value=&quot;512,384&quot;/&gt;
			&lt;Setter Property=&quot;BorderBrush&quot; Value=&quot;Black&quot;/&gt;
			&lt;Setter Property=&quot;BorderThickness&quot; Value=&quot;3&quot;/&gt;
		&lt;/Style&gt;
	&lt;/s:ScatterView.ItemContainerStyle&gt;

	&lt;s:ScatterViewItem Orientation=&quot;0&quot;&gt;
		&lt;Image Source=&quot;Resources/Img/fuente_tres_chorros.jpg&quot;/&gt;
	&lt;/s:ScatterViewItem&gt;

	&lt;s:ScatterViewItem Orientation=&quot;60&quot;&gt;
		&lt;Image Source=&quot;Resources/Img/kiyoumizu_dera.jpg&quot;/&gt;
	&lt;/s:ScatterViewItem&gt;

	&lt;s:ScatterViewItem Orientation=&quot;180&quot;&gt;
		&lt;Image Source=&quot;Resources/Img/laputa_robot.jpg&quot;/&gt;
	&lt;/s:ScatterViewItem&gt;

	&lt;s:ScatterViewItem Orientation=&quot;240&quot;&gt;
		&lt;Image Source=&quot;Resources/Img/fuente_tres_chorros.jpg&quot;/&gt;
	&lt;/s:ScatterViewItem&gt;

	&lt;s:ScatterViewItem Orientation=&quot;300&quot;&gt;
		&lt;Image Source=&quot;Resources/Img/kiyoumizu_dera.jpg&quot;/&gt;
	&lt;/s:ScatterViewItem&gt;

	&lt;s:ScatterViewItem Orientation=&quot;360&quot;&gt;
		&lt;Image Source=&quot;Resources/Img/laputa_robot.jpg&quot;/&gt;
	&lt;/s:ScatterViewItem&gt;
&lt;/s:ScatterView&gt;
</pre>
<p><a href="http://www.juanmasantoyo.es/wp-content/uploads/2010/02/03.jpg"><img src="http://www.juanmasantoyo.es/wp-content/uploads/2010/02/03-300x225.jpg" alt="" title="Definiendo las propiedades por defecto de los ScatterViews" width="300" height="225" class="aligncenter size-medium wp-image-335" /></a></p>
<h3>Es todo por hoy</h3>
<p>El componente <em>ScatterView</em> es sencillo de usar y proporciona una característica muy interesante a nuestras aplicaciones.</p>
<p>Cuando se trabaja para Surface, hay que tener muy en cuenta que los diversos usuarios se colocan alrededor de la mesa, por lo que no existe el derecho ni el revés. Los ScatterViews nos solucionarán este problema más de una vez.</p>
<p>En la siguiente parte del artículo, veremos cómo trabajar con ScatterViews desde C#.</p>
<h3>Editado 7/5/2010:</h3>
<p>Me comentaron que los códigos fuente en XAML tenían mal la sintaxis, y efectívamente; cuando he pasado a revisarlo así era. Ni idea de que pudo pasar&#8230; Bueno, ya están arreglados.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.juanmasantoyo.es/index.php/2010/04/08/introduccion-al-componente-scatterview-de-surface-parte-1/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Introducción al desarrollo sobre Microsoft Surface</title>
		<link>http://www.juanmasantoyo.es/index.php/2010/04/06/introduccion-al-desarrollo-para-microsoft-surface/</link>
		<comments>http://www.juanmasantoyo.es/index.php/2010/04/06/introduccion-al-desarrollo-para-microsoft-surface/#comments</comments>
		<pubDate>Tue, 06 Apr 2010 06:15:28 +0000</pubDate>
		<dc:creator>Juanma</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[surface]]></category>
		<category><![CDATA[microsoft]]></category>

		<guid isPermaLink="false">http://www.juanmasantoyo.es/?p=158</guid>
		<description><![CDATA[Microsoft Surface (Surface a partir de ahora) es sin duda un desafío para los programadores. Acostumbrados a entornos gráficos basados en respuestas al ratón, una interfaz de usuario multitáctil nos plantea un nuevo reto a la mayoría de nosotros.

En este artículo, pretendo dos cosas: por una parte, informarte de qué necesitas para comenzar a desarrollar y cómo obtenerlo. Por otra parte, facilitarte esa documentación que a todos nos va tan bien para empezar con una nueva tecnología. Así que vamos a ello. <a href="http://www.juanmasantoyo.es/index.php/2010/04/06/introduccion-al-desarrollo-para-microsoft-surface/">Seguir leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Microsoft Surface (Surface a partir de ahora) es sin duda un desafío para los programadores. Acostumbrados a entornos gráficos basados en respuestas al ratón, una interfaz de usuario multitáctil nos plantea un nuevo reto a la mayoría de nosotros.</p>
<p>En este artículo, pretendo dos cosas: por una parte, informarte de qué necesitas para comenzar a desarrollar y cómo obtenerlo. Por otra parte, facilitarte esa documentación que a todos nos va tan bien para empezar con una nueva tecnología. Así que vamos a ello.<br />
<span id="more-158"></span><br />
Lo primero que debes saber, es que una aplicación para Surface no es más que una aplicación WPF o XNA. Por si no lo sabías, WPF es un entorno muy potente para desarrollar aplicaciones de escritorio orientadas a los nuevos entornos gráficos de Windows Vista y Windows 7. XNA es un entorno para desarrollo de videojuegos también facilitado por Microsoft. Si has jugado con la Xbox 360 te habrás preguntado ¿de dónde salen los tantísimos juegos del bazar? Pues bien, la mayoría están desarrollados por compañías independientes con XNA.</p>
<p>Obviamente, optar por WPF o XNA dependerá de nuestra aplicación. Si necesitamos un motor rico en controles de usuario, optaríamos por WPF. Si necesitamos un motor potente en la renderización de gráficos 3D, optaríamos por XNA. Depende de las necesidades de nuestra aplicación.</p>
<p>En este artículo, pretendo dos cosas: por una parte, informarte de qué necesitas para comenzar a desarrollar y cómo obtenerlo. Por otra parte, facilitarte esa documentación que a todos nos va tan bien para empezar con una nueva tecnología. Así que vamos a ello.</p>
<p>Lo primero que debes saber, es que una aplicación para Surface no es más que una aplicación WPF o XNA. Por si no lo sabías, WPF es un entorno muy potente para desarrollar aplicaciones de escritorio orientadas a los nuevos entornos gráficos de Windows Vista y Windows 7. XNA es un entorno para desarrollo de videojuegos también facilitado por Microsoft. Si has jugado con la Xbox 360 te habrás preguntado ¿de dónde salen los tantísimos juegos del bazar? Pues bien, la mayoría están desarrollados por compañías independientes con XNA.Obviamente, optar por WPF o XNA dependerá de nuestra aplicación. Si necesitamos un motor rico en controles de usuario, optaríamos por WPF. Si necesitamos un motor potente en la renderización de gráficos 3D, optaríamos por XNA. Depende de las necesidades de nuestra aplicación.</p>
<h3>Instalación del entorno de desarrollo</h3>
<p>Para empezar, un detalle importante es nuestro sistema operativo: El SDK de Surface no funcionará en Windows XP, necesitaremos Windows Vista o superior.</p>
<p>Bien, empecemos a instalar los programas necesarios. Antes de empezar, no estaría mal asegurarse de que tenemos instalada la última versión del .Net Framework (3.5 SP1 en estos momentos).</p>
<p>La primera herramienta que debemos conseguir es un Visual Studio. Como sabrás, Visual Studio es un IDE desarrollado por Microsoft y orientado al desarrollo de aplicaciones en .Net. Si no lo tienes y eres estudiante universitario, puedes hacerte con una licencia de estudiante. Esta licencia es totalmente gratuita y sólo necesitaras proporcionar tu identificación como estudiante. Puedes obtenerla aquí: <a href="https://www.dreamspark.com/Products/Product.aspx?productid=24">Microsoft Visual Studio</a>.</p>
<p>Cuando tengamos el Visual Studio instalado, deberemos instalar el Framework de XNA (independientemente de que queramos desarrollar con WPF). Lo podemos obtener de aquí: <a href="http://www.microsoft.com/downloads/details.aspx?familyid=15fb9169-4a25-4dca-bf40-9c497568f102&#038;displaylang=en.">Microsoft XNA Framework</a>.</p>
<p>Finalmente, instalamos el SDK de Surface. Lo encontramos aquí: <a href="http://www.microsoft.com/downloads/details.aspx?displaylang=en&#038;FamilyID=3db8987b-47c8-46ca-aafb-9c3b36f43bcc">Microsoft Surface SDK</a>.</p>
<p>Con este software instalado, ya estamos listos para abrir el Visual Studio y crear un nuevo proyecto de Surface, no sin antes ejecutar el emulador de Surface que viene con el SDK. De esta forma, al depurar proyectos desde Visual Studio, se ejecutarán en el emulador.</p>
<p>Debes saber, además; que si conectas más de un ratón por USB el emulador los considerará dedos diferentes. ¡Eso es, soporte multitáctil en tu ordenador!.</p>
<h3>Recursos de documentación para empezar</h3>
<p>Ya tenemos todo lo necesario para empezar a desarrollar aplicaciones de Surface. Ahora, sólo nos falta algo de documentación que nos oriente para empezar a hacer cosas.</p>
<h4>Developing for Microsoft Surface</h4>
<p>Pero ¿dónde nos estamos metiendo realmente? En esta conferencia de Microsoft se ilustra cómo es el desarrollo de aplicaciones en Surface.<br />
<a href="http://channel9.msdn.com/pdc2008/PC17/">Developing for Microsoft Surface</a>.</p>
<h4>Hola Mundo Surface con WPF</h4>
<p>Siguiendo en la línea anterior, este artículo me ha aclarado algunos conceptos generales más a la hora de afrontar el desarrollo con Surface. Interesante sobre todo porque habla algo de los nuevos eventos de contacto de Surface.<br />
<a href="http://www.luisguerrero.net/post/2009/03/16/Hola-Mundo-Surface-con-WPF.aspx">Hola Mundo Surface con WPF</a>.</p>
<h4>MSDN .Net Framework Developer Center</h4>
<p>Pero vamos, ya está bien de conceptos generales, ¿verdad? Seguro que ya tienes ganas de meterle mano a Surface.</p>
<p>En MSDN nos facilitan información y ejemplos varios para empezar a programar algunas cosas. ¡Suerte!.<br />
<a href="http://msdn.microsoft.com/en-us/library/ee804767.aspx">MSDN .Net Framework Developer Center</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.juanmasantoyo.es/index.php/2010/04/06/introduccion-al-desarrollo-para-microsoft-surface/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

