Coming to the Surface

In my last blog entry I posted a link to the Surface Session in PDC : https://channel9.msdn.com/pdc2008/PC17/

This post is just to summarize some of the points with developing on surface.

Porting a WPF application to Surface

1) Add Reference to Surface assembly (Microsoft.Surface.Presentation)

Add the XML Namespace to the XAML file: https://schemas.microsoft.com/surface/2008

 <Window x:Class="PhotoDemo.Window1"
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:s="https://schemas.microsoft.com/surface/2008"

2) Replace the controls with s:Surface.<control>

WPF Surface
 Window
 s:Surface.Window
 Button
 s:Surface.Button
 ScrollViewer
 s:Surface.ScrollViewer
 ListBox
 s:Surface.ListBox

The only problem with this is that the application will still be displayed one way, and not give the 360 feel users would expect with a surface. This is where the ScatterView control comes in.

ScatterView

To create a ScatterView around a control simply surround it with the tag:

 <s:ScatterView>

The ScatterView contains ItemTemplates, which can bind to a DataTemplate.

e.g. for a ScatterView of Images:

 <s:ScatterView Name="Scatter">
  <s:ScatterView.ItemTemplate>
    <DataTemplate>
      <Image Source="{Binding}"/>
    </DataTemplate>
  </s:ScatterView.ItemTemplate>
</s:ScatterView>

then in the code after InitializeComponent(); populate the items source (sample pictures):

 public Window1()
{
  InitializeComponent();
  Scatter.ItemsSource = System.IO.Directory.GetFiles(@"c:\users\public\pictures\sample pictures", "*.jpg"); 
  AddActivationHandlers();
}

Compile, and you should see some pictures which you can move around the surface, resize and rotate.

ScatterView Additional Properties

The items within ScatterView have some additional properties:

 CanScale (Boolean)
CanRotate (Boolean)

DecelerationRate (Double)

These are mostly obvious (i.e. CanScale means the user is able to enlarge and reduce the controls by dragging in opposite directions with fingers, CanRotate means the user is able to turn controls by moving fingers around in a circular motion, and DecelerationRate is how much “friction” there is on the surface when a control is thrown.

 <s:ScatterView>
  <s:ScatterView.ItemTemplate>
    <Style TargetType="{x:Type s:ScatterViewItem}">
      <Setter Property="CanScale" 
              Value="{Binding ElementName=scale, Path=IsChecked}" />
      <Setter Property="CanRotate" 
              Value="{Binding ElementName=rotate, Path=IsChecked}" />
      <Setter Property="CanScale" 
              Value="{Binding ElementName=decel, Value}" />
    </Style>
</s:ScatterView>
<StackPanel Width="200" Height="120" Background="Gray">
  <s:SurfaceCheckBox Name="scale" IsChecked="True" FontSize="20">
    CanScale
  </s:SurfaceCheckBox>
  <s:SurfaceCheckBox Name="rotate" IsChecked="True" FontSize="20">
    CanRotate
  </s:SurfaceCheckBox>
  <Label FontSize="20">Deceleration Rate:</Label>
  <s:SurfaceSlider Name="decel" Minimum="1" Maximum="6000" />
</StackPanel>

The Minimum and Maximum values are in device independent pixels per second per second (i.e. lower number is slippery, higher is rougher)

Tagged Objects

The final part of this session was for recognizing when objects are put onto the surface.  The items should have a tag either

 Contact.Tag.Byte

or

 Contact.Tag.Identity

The Byte tag contains 256 different ID’s, whereas the Identity Tag allows 340,282,366,920,938,000,000,000,000,000,000,000,000 different ID’s

These not only recognise a specific object, but also the position and orientation of the object.

You can create custom controls or TagVisualizer which allows custom UI’s for each Tag recognised, how to handle the object being removed form the surface.

 <s:TagVisualizer>

To allocate this with a tag

 <s:TagVisualizer>
  <s:TagVisualizer.Definitions>
    <s:ByteTagVisualizationDefination
      Source="<xaml file for Visualization>"
      Value="<Value written on the tag, example hex>0x40"
      PhysicalCenterOffsetFromTag="<x,y values of center offset between object and Visualization> e.g. -.23,-.4"
      OrientationOffsetFromTag="<Rotational offset between tag on object and Visualization (may be measured clockwise in degrees)>e.g. 266" />
  </s:TagVisualizer.Definitions>
</s:TagVisualizer>

I’ll look forward to playing around with this some more in the future (fingers crossed)