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 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.
Sobre el componente ScatterView
Un ScatterView representa un elemento que reacciona a los contactos sobre Surface y que se puede mover, rotar o redimensionar.
El ejemplo más clásico sería un puñado de fotografías. Cada una de esas fotografías puede ser un ScatterView.
Preparamos el proyecto
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.
Creamos el proyecto
Nuestro proyecto va a ser una aplicación para Surface basada en WPF. Lo llamaremos HelloScatterView.
Al crear nuestro proyecto se nos ha creado una ventana por defecto: SurfaceWindow1. La renombraremos, y le pondremos el nombre de “XamlSample“.
Añadimos unas imágenes
Para poder trabajar con los ScatterViews, necesitaremos algunas imágenes.
Dentro de nuestro proyecto Surface tenemos una carpeta llamada Resources. Crearemos otra carpeta en su interior llamada Img y ubicaremos ahí nuestras imágenes.
Añadir ScatterViews desde XAML
ScatterView simple con XAML
Comenzaremos usando los ScatterViews desde XAML. En realidad añadir un ScatterView es muy simple:
<s:ScatterView>
<Image Source="Resources/Img/fuente_tres_chorros.jpg"/>
</s:ScatterView>

Este es el código que añade un ScatterView. Fijaos en un detalle: añadir un ScatterView no es sólo añadir el nodo ScatterView, también es añadir el recurso que se manejará, en este caso la imagen. Y es que un ScatterView no es una imagen, sino la capacidad que tiene un elemento (en este caso una imagen) de ser rotado, redimensionado y movido.
El XAML completo de la ventana es este:
<s:SurfaceWindow
x:Class="HelloScatterView.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"
Title="HelloScatterView">
<s:SurfaceWindow.Resources>
<ImageBrush x:Key="WindowBackground"
Stretch="None" Opacity="0.6"
ImageSource="pack://application:,,,/Resources/WindowBackground.jpg"/>
</s:SurfaceWindow.Resources>
<s:ScatterView>
<Image Source="Resources/Img/fuente_tres_chorros.jpg"/>
</s:ScatterView>
</s:SurfaceWindow>
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.
Vamos a hacerlo un poco más espectacular añadiendo varias imágenes:
<s:ScatterView>
<Image Source="Resources/Img/fuente_tres_chorros.jpg"/>
<Image Source="Resources/Img/kiyoumizu_dera.jpg"/>
<Image Source="Resources/Img/laputa_robot.jpg"/>
<Image Source="Resources/Img/fuente_tres_chorros.jpg"/>
<Image Source="Resources/Img/kiyoumizu_dera.jpg"/>
<Image Source="Resources/Img/laputa_robot.jpg"/>
</s:ScatterView>

Scatterviews complejos con XAML
Probablemente ya te estés preguntando lo siguiente: ¿cómo determinar los parámetros por defecto de nuestro ScatterView? Vamos a ello.
La clave está en que la estructura que hemos usado ahora no acaba de ser la mejor. En realidad, nos está faltando crear un ScatterViewItem, que hasta el momento se estaba creando de forma automática para cada elemento en el ScatterView.
<s:ScatterView> <s:ScatterViewItem> <Image Source="Resources/Img/fuente_tres_chorros.jpg"/> </s:ScatterViewItem> </s:ScatterView>
En el nodo ScatterViewItem podemos establecer muchas propiedades que afectarán al comportamiento de nuestro ScatterView.
Algunas de esas propiedades son:
- MinWidth, MaxWidth, MinHeight, MaxHeight: Máximos y mínimos de anchura y altura.
- CanMove, CanRotate, CanScale: Activan o desactivan las capacidades de mover, rotar y redimensionar.
- Width, Height, Center, Orientation: Valores iniciales para el ancho, el alto, la posición, y la rotación.
- BorderBrush, BorderThikness: Color y grosor del borde.
Un ejemplo sencillo:
<s:ScatterView> <s:ScatterViewItem Center="512,384" Orientation="0"> <Image Source="Resources/Img/fuente_tres_chorros.jpg"/> </s:ScatterViewItem> <s:ScatterViewItem Center="512,384" Orientation="60"> <Image Source="Resources/Img/kiyoumizu_dera.jpg"/> </s:ScatterViewItem> <s:ScatterViewItem Center="512,384" Orientation="180"> <Image Source="Resources/Img/laputa_robot.jpg"/> </s:ScatterViewItem> <s:ScatterViewItem Center="512,384" Orientation="240"> <Image Source="Resources/Img/fuente_tres_chorros.jpg"/> </s:ScatterViewItem> <s:ScatterViewItem Center="512,384" Orientation="300"> <Image Source="Resources/Img/kiyoumizu_dera.jpg"/> </s:ScatterViewItem> <s:ScatterViewItem Center="512,384" Orientation="360"> <Image Source="Resources/Img/laputa_robot.jpg"/> </s:ScatterViewItem> </s:ScatterView>
Aunque de hecho, podemos centralizar la mayoría de estas propiedades en un único nodo, como un estilo:
<s:ScatterView>
<s:ScatterView.ItemContainerStyle>
<Style TargetType="{x:Type s:ScatterViewItem}">
<Setter Property="Center" Value="512,384"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="BorderThickness" Value="3"/>
</Style>
</s:ScatterView.ItemContainerStyle>
<s:ScatterViewItem Orientation="0">
<Image Source="Resources/Img/fuente_tres_chorros.jpg"/>
</s:ScatterViewItem>
<s:ScatterViewItem Orientation="60">
<Image Source="Resources/Img/kiyoumizu_dera.jpg"/>
</s:ScatterViewItem>
<s:ScatterViewItem Orientation="180">
<Image Source="Resources/Img/laputa_robot.jpg"/>
</s:ScatterViewItem>
<s:ScatterViewItem Orientation="240">
<Image Source="Resources/Img/fuente_tres_chorros.jpg"/>
</s:ScatterViewItem>
<s:ScatterViewItem Orientation="300">
<Image Source="Resources/Img/kiyoumizu_dera.jpg"/>
</s:ScatterViewItem>
<s:ScatterViewItem Orientation="360">
<Image Source="Resources/Img/laputa_robot.jpg"/>
</s:ScatterViewItem>
</s:ScatterView>
Es todo por hoy
El componente ScatterView es sencillo de usar y proporciona una característica muy interesante a nuestras aplicaciones.
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.
En la siguiente parte del artículo, veremos cómo trabajar con ScatterViews desde C#.
Editado 7/5/2010:
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… Bueno, ya están arreglados.

8 de abril del 2010 at 17:34
Hola de nuevo
Gracias por el artículo, muy bueno, pero aun con dudas
no se si tenga que ver la version de visual Studio que tengo, es la 2008 professional, cuando genero un nuevo proycto de microsoft surface me da por default este código:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
using Microsoft.Surface;
using Microsoft.Surface.Presentation;
using Microsoft.Surface.Presentation.Controls;
namespace HelloScatterView
{
///
/// Interaction logic for SurfaceWindow1.xaml
///
public partial class SurfaceWindow1 : SurfaceWindow
{
///
/// Default constructor.
///
public SurfaceWindow1()
{
InitializeComponent();
// Add handlers for Application activation events
AddActivationHandlers();
}
///
/// Occurs when the window is about to close.
///
///
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
// Remove handlers for Application activation events
RemoveActivationHandlers();
}
///
/// Adds handlers for Application activation events.
///
private void AddActivationHandlers()
{
// Subscribe to surface application activation events
ApplicationLauncher.ApplicationActivated += OnApplicationActivated;
ApplicationLauncher.ApplicationPreviewed += OnApplicationPreviewed;
ApplicationLauncher.ApplicationDeactivated += OnApplicationDeactivated;
}
///
/// Removes handlers for Application activation events.
///
private void RemoveActivationHandlers()
{
// Unsubscribe from surface application activation events
ApplicationLauncher.ApplicationActivated -= OnApplicationActivated;
ApplicationLauncher.ApplicationPreviewed -= OnApplicationPreviewed;
ApplicationLauncher.ApplicationDeactivated -= OnApplicationDeactivated;
}
///
/// This is called when application has been activated.
///
///
///
private void OnApplicationActivated(object sender, EventArgs e)
{
//TODO: enable audio, animations here
}
///
/// This is called when application is in preview mode.
///
///
///
private void OnApplicationPreviewed(object sender, EventArgs e)
{
//TODO: Disable audio here if it is enabled
//TODO: optionally enable animations here
}
///
/// This is called when application has been deactivated.
///
///
///
private void OnApplicationDeactivated(object sender, EventArgs e)
{
//TODO: disable audio, animations here
}
}
}
al incluir el código que facilitas para agregar el sctatter view me marca algunos erroes.
otra duda, donde encuntr l carpeta resources???
gracias por tu tempo, buena tarde!!1
9 de abril del 2010 at 0:06
Hola!!!!
ya me di un clavadsimo en todo esto, logre solucionar mis dudas, ahora solo una pregunta
Sabes como hacer que se volteen las imagenes (como si le dieras vuelta a una carta en la mesa) estoy preparando un memorama y me seria de gran utilidad
Un saludo y de nuevo gracias
9 de abril del 2010 at 6:12
Hola!
Ciértamente, aplicar un flip sobre un ScatterView es una solución muy interesante para interfaces táctiles como Surface.
Debo confesar que aún no he podido documentarme sobre el efecto de flip, aunque una rápida búsqueda en Google me la llevado a un post interesante en los foros de microsoft:
http://social.msdn.microsoft.com/Forums/en/surfaceappdevelopment/thread/edc68262-f1ae-4337-aa4d-b7beb8cfee44
Espero que puedas sacarle partido
.
9 de abril del 2010 at 16:19
Lo consultare, estudiare y exprimire hasta donde pueda
te agradezco un saludo
9 de abril del 2010 at 23:20
Otra duda tal vez me termines odiando jeje
sabes como dar funciones a los scatteview en c# con un click
por ejemplo, que al dar click en una imagen se cambie el texto de unacaja e texo
Gracias!!!!
9 de abril del 2010 at 23:25
Hola.
Algo he encontrado sobre el tema, puede que esto te sirva de ayuda:
http://msdn.microsoft.com/en-us/library/ee804980%28v=Surface.10%29.aspx
12 de abril del 2010 at 16:39
Hola de nuevo, todo corriendo de maravilla, agradeciendo los comentarios, me han ayudado, solo me falta, como se declaran las varibles?? deseo agregar un contador y para el siguiente proyecto necesito agregar mas.
po jemplo que se guarde el nombre, que al presionar un boton x veces se guarde el numero que se guardo
Gracias de nuevo!!!
12 de abril del 2010 at 17:07
¡Vaya! Por fín me haces una pregunta facil xD.
Pues los contadores son sencillos, en el fondo es una aplicación orientada a objetos como otra cualquiera. Por ejemplo, si queremos contar las veces que se hace click en un boton:
1. Primero creamos una variable global en la ventana que sea el contador:
public class …
{
…
int contador = 0;
…
2. Después, en el manejador del evento click del botón:
public void Manejador_Click(…
{
…
this.contador ++;
…
}
Y no tiene más misterio que este. En cualquier momento puedes mirar que valor tiene el contador ya que es una propiedad global.
Un saludo.
13 de abril del 2010 at 1:57
Hola de nuevo… tal vez teburles, pero no le encontre como para el cotador, jeje no si me podrias yudar con otro ejempo ponendo todolo la clase??? graca
D:D
13 de abril del 2010 at 5:55
Nop, no me burlo por que yo no nací sabiendo hacer contadores xD.
Hacer un pequeño ejemplo será sencillo, en unos días lo publicaré.
14 de abril del 2010 at 23:52
hola de nuevo, ya me salieron lo contadores jeje gracias de nuevo!!!
otra duda, sabes como incluir un timer???
Ya me hasde soñar con tanta molestia je
15 de abril del 2010 at 6:05
Pues mira, precisamente ayer aprendí sobre Timers.
Mira, básicamente, si tu timer funciona de forma independiente, usa la clase Timer:
http://msdn.microsoft.com/es-es/library/system.timers.timer%28VS.80%29.aspx
Pero si quieres un timer donde puedas acceder a elementos de la interfaz gráfica y este tipo de cosas, necesitarás la clase DispatcherTimer.
http://msdn.microsoft.com/en-us/library/ms615945%28v=VS.100%29.aspx
16 de abril del 2010 at 19:35
Hola, Gracias por el timer, too bien
ahora ando trabajando en un proyecto mas serio, necesito sacar datos del directorio activo dela empresa y despegarlos enel surface, sabes ago de manejo de directorio activo?
gracias.. de nuevo
16 de abril del 2010 at 20:06
Hola.
Bueno, ahí si que me pillas. La verdad es que no se mucho del tema xD.
28 de abril del 2010 at 19:31
Hola, rato de no escribir
estaba leyendo lo de directorio activo ultimamente y tratando de instalar en sdk en 64 bits, el directorio activo es posible hacerlo, pero se necesita hacerle una conexion con sql y despues leer los datos desde C#, algo complicado, pero empiezan a aparecer resultados… por fin!!! jeje
espero saque nuevo articulo pronto
Saludos!!!
Pingback: Juanma Santoyo » Blog Archive » Introducción al componente ScatterView de Surface (2: ScatterViews con C#)