Starting your PixelSense Application Efficiently
When you start to build an application for the SUR40 and Microsoft PixelSense, all used to work really perfectly well on the simulator and your development PC. When you start to install and run your application directly on the device in Surface mode, you start to face a challenging but important issue:
Get your application started before the Surface Shell timeout
All of us found the famous startup time-out handle by the Surface shell. It could happen that your application appears to never start in that mode or it starts but not all the time.
Never block the main UI thread
The entry point of your Surface application is the main surface window, and this is also the main UI thread for your application. If you perform some long operation within the loading process of that main Window, you are blocking the main UI thread and you will definitely get the famous time-out message
How does it really work
A Microsoft Surface application must not block the UI thread for more than 5 seconds. If it does so, the system closes and tries to restart the unresponsive applications twice. If it must close the application the third time because of unresponsiveness, Surface returns to Launcher and does not try any further restarts.
Loading your application while using potentially long loading of controls
When you start to build an application, you usually start to fill up your SurfaceMainWindow.xaml grid with the different control that you think you need to load.
The following code snapshot shows that scenario:
Potentially Locked Main Surface windows loading process
<s:SurfaceWindow x:Class=”SurfaceAppStartup1.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:controls=”clr-namespace:SurfaceAppStartup1.Controls”
Title=”SurfaceAppStartup1″
>
<Grid x:Name=”Content” Height=”Auto”>
<s:SurfaceScrollViewer x:Name=”_mainHScrollViewer” ScrollChanged=”_mainHScrollViewer_ScrollChanged”
Width=”{Binding Element Name=Main, Path=Width}”
PanningMode=”None”
HorizontalScrollBarVisibility=”Hidden”
VerticalScrollBarVisibility=”Hidden” DataContext=”{Binding}”>
<StackPanel x:Name=”AppPanel” Orientation=”Horizontal” Background=”Transparent” >
<!– Load background Window –>
<controls:BackgroundImage DataContext=”{Binding}”/>
<!– Load WordMapControl –>
<controls:WorldMapControl/>
</StackPanel>
</s:SurfaceScrollViewer>
</Grid>
</s:SurfaceWindow>
From the sample above, you can see that we are instantiated directly in Xaml the loading of the WorldMapControl UserControl as <controls:WorldMapControl/>. In this case, if the loading time that that control is longer than plan your main UI thread will be blocked and you will get the Surface Shell Time-Out.
Solution : Use of Content control and Binding
From the sample above, we simply replace the <controls:WorldMapControl/> by the code below :
<ContentControl DataContext=”{Binding Source={StaticResource Locator}, Path=WorldMapViewModelStatic}”
Content=”{Binding MapControl, UpdateSourceTrigger=PropertyChanged}” />
You can guess from the code above that we are using binding and an MVVM pattern to reach our goal. By doing so, the main UI thread will not be blocked during the loading of the control. Instead, it will prepare a Content control that will have its Content property bind to a MVVM property named MapControl. When the MapControl property change, the control will be injected in the ContentControl.
What to do then while my user will wait for control to load?
This is a really interesting question and there are different approach. First avoid using a simple loading screen without adding value for the user. Remember that as soon as a Surface application has started, the application is interactive and user expects to do something with it:
- Provide simple content information in relation with your application that users can already explore
- Indicate visually that remaining contents are currently loading
- When the remaining controls have completed and the full application is ready, bring attention to users with visual component or effect that something more can be done
Important:
When all your application initialization content is done, your application must call the Microsoft.Surface.ApplicationServices.SignalApplicationLoadComplete method to dismiss the opening activity when the application is ready to appear. If your application does not call that method, it Surface shell will wait for the end of the time out process.
Remark: ( msdn source)
Applications that are hosted in a SurfaceWindow control do not need to (and should not) call the SignalApplicationLoadComplete method if the AutoSignalLoadComplete property is true (the default value). In this case, the SurfaceWindow control calls SignalApplicationLoadComplete automatically.
If your application is not hosted in a SurfaceWindow control, or if you set the AutoSignalLoadComplete property to false, your application must call SignalApplicationLoadComplete when your application has completed initialization. This call causes Launcher to dismiss the loading screen and display your application on the Surface screen.
The SignalApplicationLoadComplete method must be called (either automatically or manually) only once during the lifetime of the application.
You can download sample project which illustrate this from the MSDN code sample.
Hoping this small post will be helpful for you.