Scrolling in Windows Store applications is mostly done in horizontal mode. This is something quite easy to do with the GridView which support scrolling with mouse wheel but this can be a quite more complicated to do in Webview.

Indeed, in the Webview control, the mouse wheel scroll is done in vertical mode so here is a quick fix to perform the same scroll in horizontal mode.

To do this, you can use a JQuery plugin like JQuery.MouseWheel: https://github.com/brandonaaron/jquery-mousewheel

In your Webview, load JQuery and this plugin:

var scriptJQuery = "<script type='text/javascript' src='http://code.jquery.com/jquery-1.7.js'></script>";
var scriptJQueryMouseWheel = "<script type='text/javascript' src='ms-appx-web:///Views/web/jquery.mousewheel.js'></script>";

var content = "<!doctype html><html lang=\"fr\"><head><link rel=\"stylesheet\" href=\"ms-appx-web:///Views/web/web.css\" type=\"text/css\" media=\"screen\" />" scriptJQuery + scriptJQueryMouseWheel + "</head>" +
    "<div id=\"articleContent\"><font id=\"article\" face=\"Segoe UI\">" +
        SelectedNews.Description +
    "</div></font>" +
"</html>";

webView.NavigateToString(content);

Once this is done, we can just add a small JavaScript function to handle the “MouseWheel” event:

var mouseWheelScript = "<script type=\"text/javascript\">" +
                        "$(function() {" +
                            "$('html, body').mousewheel(function(event, delta) {" +
                                "this.scrollLeft -= (delta * 50);" +
                                "event.preventDefault();" +
                            "});" +
                        "});" +
                    "</script>";

So the complete code is the following one:

var scriptJQuery = "<script type='text/javascript' src='http://code.jquery.com/jquery-1.7.js'></script>";
var scriptJQueryMouseWheel = "<script type='text/javascript' src='ms-appx-web:///Views/web/jquery.mousewheel.js'></script>";

var mouseWheelScript = "<script type=\"text/javascript\">" +
                        "$(function() {" +
                            "$('html, body').mousewheel(function(event, delta) {" +
                                "this.scrollLeft -= (delta * 50);" +
                                "event.preventDefault();" +
                            "});" +
                        "});" +
                    "</script>";

var content = "<!doctype html><html lang=\"fr\"><head><link rel=\"stylesheet\" href=\"ms-appx-web:///Views/web/web.css\" type=\"text/css\" media=\"screen\" />" + scriptResize + scriptVideo + scriptJQuery + scriptJQueryMouseWheel + mouseWheelScript + "</head>" +
    "<div id=\"articleContent\"><font id=\"article\" face=\"Segoe UI\">" +
        SelectedNews.Description +
    "</div></font>" +
"</html>";

webView.NavigateToString(content);

Now, each time the Webview will get the focus, user will be able to perform a horizontal scrolling using the mousewheel.

Pretty simple when you know!

Please note that the plugin’s file is loaded from ms-appx-web to allow Webview to load it correctly.

 

Happy coding!

Here is a problem we met recently with my colleague Jonathan.

Indeed, in one of the Windows 8 applications we are working, we have a Webview that is loaded thanks to the method NavigateToString:

WebviewNews.NavigateToString(content);

(where content is the HTML fragment that will be displayed in the Webview).

On that HTML, we wanted to insert a custom CSS file so we tried the following:

 var content =
    "<html><head><link rel=\"stylesheet\" href=\"ms-appx:///Views/web/web.css\" type=\"text/css\" media=\"screen\" /></head>" +
         "<font face=\"Segoe UI\">" +
             NewsDetailPageViewModel.SelectedNews.Description +
         "</font>" +
     "</html>";
 WebviewNews.NavigateToString(content);

Unfortunately, this does not work: the code is correct but the CSS rules were not applied.

After a quick look, it appears that the fix is simple: instead of using ms-appx, we needed to use ms-appx-web. Content referenced via this scheme is loaded from the local package, but runs with the abilities and restrictions of the web context.

The correct code was:

 var content =
    "<html><head><link rel=\"stylesheet\" href=\"ms-appx-web:///Views/web/web.css\" type=\"text/css\" media=\"screen\" /></head>" +
         "<font face=\"Segoe UI\">" +
             NewsDetailPageViewModel.SelectedNews.Description +
         "</font>" +
     "</html>";
 WebviewNews.NavigateToString(content);

Using this syntax, the CSS rules were correctly loaded and the HTML content was correctly modified according to our CSS rules.

 

Happy coding!

I’m glad to announce that my first MSDN article (Building and Validating Windows Store Apps with Team Foundation Service) is now available !

It’s a topic I’ve already covered on my blog but I hope you’ll get more information and details in the new and revisited version!

The article is available here: http://msdn.microsoft.com/en-us/magazine/dn166931.aspx

Happy coding (and building) !

If you’ve never tried TFS Service yet, you might give it a try right now. Indeed, based on Team Foundation Server 2012, it provides to developers source control feature, build, test and more!

The Build service is really cool because you’ll be able to build any kind of applications and, because it’s cloud-based, you won’t need to have your server running by yourself!

But, even if it’s cool, Build service on TFS Service is still in preview and so, there might be some issues. The first one is that you can’t build Windows Store apps. Indeed, if you try, you’ll encountered the following error:

image

At least, this is a very clear message. Fortunately, as it’s based on TFS 2012, we’ll be able to add a new Build Controller/Agent to indicate to TFS Service that we want to build Windows Store apps on a particular machine (one with Windows 8).

So, first step is to create a Windows 8 virtual machine (I won’t detailed this procedure here as it’s easy to do). Once the VM is ready, we can install all the stuff that we might need: Visual Studio 2012, Windows SDK, etc. (I know that installing VS on build machine might not be the proper way to do but, at least, it works every time).

Once the machine is ready, we’ll add a new build controller and build agent on it. For that, start the installation of Team Foundation Server 2012:

image

Once the installation is done, the Configuration Center is displayed on screen. Here, we won’t choose to configure Team Foundation Application Server but only the Team Foundation Build Service so select this entry and click on “Start Wizard”:

image

On the next screen that appears, you are asking to select the Team Project collection you are configuring build services for:

image

So click on the “Browse” button and add your TFS Service server:

image

Once authenticated, you can select the Team Project Collection that you want:

image

Then, you’ll be back to the previous screen, with the information dedicated to the build services for your team project collection (if you just start, you may see the same thing as the screenshot below: 0 build controller(s) and 0 build agent(s) because even if there are already a build controller/agent for TFS Service, they are is idle state until you trigger a new build):

image

Next, you are ask to configure the number of build controller(s)/agent(s) you want to install on the machine. For now, we’ll just install the build service so choose to configure later (we’ll do it after):

image

Please, note that the number of build agent(s) recommended is proposed according by your server specs (as build agents run concurrently and do processor-intensive work).

Next, you need to provide the account that will run the Build Service. You can use one of the system account but I’m not a big fan of this possibility. I prefer to create dedicated account (but feel free to do as you want for this part):

image

Once the readiness checks has been validated, you’re ready to configure the Build Service:

image

image

Once finish, click on “Close”:

image

You can now see that the Build Service is installed and configured:

image

Now that the service is installed, it’s time to add a controller and an agent. Launch the Team Foundation Server Administration Console from the Start Menu:

image

From the console, select “Build Configuration” to see that the Build Service is configured for the Team Project Collection you’ve chosen and that there is no controller(s)/agent(s):

image

Now, we’ll add a new controller to the Build Service. Why this is needed ? Because you cannot add/attach an on-premise build agent to a hosted build controller (the one available in TFS Service):

image

So click on the “New Controller…” link and add a new one:

image

Once the controller is up & running, we are now ready to add an agent on it so click on the link “New Agent…”:

image

Be sure to select the controller that you’ve just created otherwise, you’ll encountered the previous error. Also, note that I’ve added a tag. This is not necessary but when I’ll create the build definition (later), it’ll help to to be sure that only this agent will be used because this is the only one able to build Windows 8 apps

image

Now that controller and agent are ready, it’s the moment to create the Build definition that will use them to build Windows 8 apps:

image

In Visual Studio, open the Team Explorer, select “Builds” and, under “Actions”, click on “Manage Build Controllers…”:

image

The screen that appears display the list of all controllers/agents available for the Team Project Collection and, as you can see, the controller and agent we have created are correctly displayed (marked as Available):

image

Now, click on the link “New Build Definition” and fill the information needed (I won’t detailed all the screens as they are simples). the most important part is the “Build Defaults” where you have to select the controller we have installed previously and the path where the build outputs will be sent:

image

One the next screen (“Process”), choose the items to build but, most important (under Advanded –> Agent Settings), select the tag corresponding to the agents you want to use to perform this build:

image

image

Save the build definition then start a new build:

image

And voila ! :)

image

The build has been executed successfully and, if you look in the output/drop folder, you’ll see that the package has been deployed correctly:

image

 

Bonus:

Now that your build service is able to build Windows Store apps, you can keep your Virtual Machine on your own DataCenter or, thanks to Windows Azure Virtual Machine, you can upload it in Windows Azure to use it from here. The task to upload a VHD in Windows Azure is really well described here http://www.windowsazure.com/en-us/manage/windows/common-tasks/upload-a-vhd/ or here http://msdn.microsoft.com/en-us/library/windowsazure/gg465385.aspx

Once uploaded (be careful, it can take a very long time according to the VM size), follow the following steps to create a Virtual Machine from VHD (in Windows Azure): http://www.cloudtec.ch/blog/tech/create-virtual-machine-vhd-in-azure.html

 

Now, you don’t have any excuse to not have a real continuous integration for you Windows Store apps!

 

Happy building!

ASP.NET SignalR is a project developed by Microsoft to allow developers to add real-time web functionality to your applications. Here is the official description of the project:

ASP.NET SignalR is a new library for ASP.NET developers that makes it incredibly simple to add real-time web functionality to your applications. What is “real-time web” functionality? It’s the ability to have your server-side code push content to the connected clients as it happens, in real-time.

You may have heard of WebSockets, a new HTML5 API that enables bi-directional communication between the browser and server. SignalR will use WebSockets under the covers when it’s available, and gracefully fallback to other techniques and technologies when it isn’t, while your application code stays the same.

SignalR also provides a very simple, high-level API for doing server to client RPC (call JavaScript functions in your clients’ browsers from server-side .NET code) in your ASP.NET application, as well as adding useful hooks for connection management, e.g. connect/disconnect events, grouping connections, authorization.

So as soon as you plan to push content from your server to one (of more) of clients, you might take a look at SignalR. I’ve started to play with it this week (a good way to start the new year) and so, here is a brief introduction to this (and powerful) framework!

First, on the server side, you have to add a reference to the correct Nuget package (be careful, the project is not in the stable branch yet):

image

Then, you have to create a Hub, in other words a kind of endpoint that will expose the methods to all the clients. Defining a hub just mean create a class that derive from the Hub class:

public class DemoHub : Hub
{
    public void Send(string message)
    {
        Clients.All.getMessage(message);
    }

    public string SayHello(string name)
    {
        return "Hello" + name;
    }
}

Deriving from the Hub class allows you to access to the Clients property which can be used to access:

  1. To all the clients connected (through the All property),
  2. To the caller of the method (through the Caller property),
  3. Etc

image

Once that you get access to the list of clients you want, you can call the methods that you want on that clients (here, on our code, we call the getMessage of each clients, passing in parameter needed):

public void Send(string message)
{
    Clients.All.getMessage(message);
}

Of course, you can also defined some methods that will be called by the clients:

public string SayHello(string name)
{
    return "Hello" + name;
}

Now that the server part is done, we can start the client part. SignalR have Nuget packages for most of the client API: .NET, Windows Phone, WinRT, Silverlight and even Javascript: this is very powerful !

First, we need to create a connection to the Web Server:

var connection = new HubConnection("http://localhost:49449/");

Once this is done, we can create a proxy that will allow us to invoke methods on the server (and being notified when the server call a method on the clients): it’s the same job as the WCF proxy created when you add a service reference (except that this new one is not strongly typed):

var proxy = connection.CreateHubProxy("DemoHub");

You can see that the CreateHubProxy method takes in parameter the class name of the Hub you’ve created on the Web Server. If you want, you can use the HubName attribute (on the Hub class) to get a kind of alias for your hub:

[HubName("MyHubTest")]
public class DemoHub : Hub

In that case, the method CreateHubProxy will look like:

// Create a proxy to the service
var proxy = connection.CreateHubProxy("MyHubTest");

Next, you have to perform 2 things:

  1. Add a kid of event handler to all the methods that will be called by the server of the clients
  2. Start the connection

If the second one is really simple (just call the Start method of the HubConnection type), the first one is simple too. Indeed, on the proxy you’ve created, you can use the extension method On, that takes in parameters:

  1. The name of the “event” you want to be notified
  2. An Action (and its parameters) corresponding to the parameters sent from the server

image

So, in our case, if we want to be notified when the method getMessage is called from the server, we just need to use the following code:

proxy.On("getMessage", message =>
{
    this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => lb.Items.Add(message));
});

// Start the connection
await connection.Start();

Pretty simple!

Lastly, we need to be able to invoke the methods defined on the Hub so we’ll use the method Invoke of the proxy:

// Call the method on the server
await proxy.Invoke("Send", "My name is WinRT");

// Call the method on the server and get the result
var s = await proxy.Invoke<string>("SayHello", "Tom");

Now, let’s use the same code from an application console:

// Connect to the service
var connection = new HubConnection("http://localhost:49449/");

// Create a proxy to the service
var proxy = connection.CreateHubProxy("DemoHub");

// Start the connection
await connection.Start();

// Call the method on the server
await proxy.Invoke("Send", "My name is Console");

(As you can see, the code is strictly the same !)

If we launch the application from the Windows 8 side (the one where the handler to getMessage has been set), we can see that all the messages has been sent to the server and broadcast to the clients:

image

So, as you can see, getting push system in any kind of applications is pretty easy using SignalR. If you want to get more info, you can take a look at the Wiki. Also, don’t hesitate to go to David Fowler’s blog, the main developer of the project.

 

Happy coding!

In Windows Store applications, the Settings contract offers to developers the possibility to add link to the Charms bar, under the Settings part:

The Settings are simple links to some page that will be display in the Settings flyout when the user will click on it:

app.onsettings = function (args) {
       var settings =
       {
           "About":
           {
               title: "About",
               href: "/Pages/otherPages/aboutPage.html"
           }
       };

       args.detail.applicationcommands = settings;

       WinJS.UI.SettingsFlyout.populateSettings(args);
};

This is great if you want to display a page from your application to the user but what happens if you just want to launch an Internet link when user click on one of your Settings link?

Well, as always, there is a code for that and this one is pretty simple: just add an event handler to the CommandRequested event of the SettingsPane and add your link directly within it:

function setupSettingsPane() {
        var settingsPane = Windows.UI.ApplicationSettings.SettingsPane.getForCurrentView();
        settingsPane.addEventListener("commandsrequested", function (eventArgs) {

        var launchBlogCommand = new Windows.UI.ApplicationSettings.SettingsCommand("LaunchBlogCmd", "My Blog", function () {
            var uri = new Windows.Foundation.Uri("http://blog.thomaslebrun.net);

            Windows.System.Launcher.launchUriAsync(uri);
        });

        eventArgs.request.applicationCommands.append(launchBlogCommand);
    });
};

(Note that even if the code provided here is in JavaScript, the same results can be achieved using C# !)

 

Happy coding!

One of my co-worker wanted to have, in its application, a FlipView that can change automatically its content. Changing the SelectedIndex property is quite good but not enough because the change is hard and he wanted to have an animation when the item change.

After taking a look at the template of the FlipView, it appears that it’s just a ScrollViewer containing an ItemsPresenter. So basically, what I needed to do was to find a way to animate the HorizontalOffset property of the ScrollViewer. Unfortunately, you won’t be able to animate this property directly. But, as you’ll find here, there is a solution that consist of using a Mediator (thanks David Anson for the tip and your good posts on Silverlight !).

Finally, if you want to animate your custom Dependency Property, you’ll need to add if to the Visual Tree (as it’s confirmed here).

So now, let’s take a look at the code ! Here is the code behind of the control:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Animation;

namespace AnimatedFlipView
{
    public class AnimatedFlipView : FlipView
    {
        private ScrollViewer _scrollViewer;
        private ScrollViewerOffsetMediator _mediator;

        private bool _isRunningAnimation;
        private bool _reverseAnimation;

        public AnimatedFlipView()
        {
            DefaultStyleKey = typeof (AnimatedFlipView);

            this.Loaded += OnLoaded;
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            if (this._scrollViewer != null && this._mediator != null)
            {
                var timer = new DispatcherTimer();
                timer.Interval = TimeSpan.FromSeconds(3);
                timer.Tick += (o, o1) =>
                {
                    if (!this._isRunningAnimation)
                    {
                        var sb = new Storyboard();

                        var nextItemAnimation = new DoubleAnimation
                        {
                            EnableDependentAnimation = true,
                            Duration = new Duration(TimeSpan.FromSeconds(2)),
                            From = this._scrollViewer.HorizontalOffset,
                            To = this._reverseAnimation ? this._scrollViewer.HorizontalOffset - 1 : this._scrollViewer.HorizontalOffset + 1,
                            FillBehavior = FillBehavior.HoldEnd,
                            EasingFunction = new ExponentialEase
                            {
                                EasingMode = EasingMode.EaseOut
                            }
                        };

                        Storyboard.SetTarget(nextItemAnimation, this._mediator);
                        Storyboard.SetTargetProperty(nextItemAnimation, "HorizontalOffset");

                        sb.Children.Add(nextItemAnimation);

                        sb.Completed += (sender1, o2) =>
                        {
                            if (this._reverseAnimation)
                            {
                                if (this.SelectedIndex > 0)
                                {
                                    this.SelectedIndex--;
                                }

                                if (this.SelectedIndex == 0)
                                {
                                    this._reverseAnimation = false;
                                }
                            }
                            else
                            {
                                if (this.Items != null && this.SelectedIndex < this.Items.Count - 1)
                                {
                                    this.SelectedIndex++;
                                }

                                if (this.Items != null && this.SelectedIndex == this.Items.Count - 1)
                                {
                                    this._reverseAnimation = true;
                                }
                            }

                            this._isRunningAnimation = false;
                        };

                        sb.Begin();

                        this._isRunningAnimation = true;
                    }
                };
                timer.Start();
            }
        }

        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this._scrollViewer = this.GetTemplateChild("ScrollingHost") as ScrollViewer;
            this._mediator = this.GetTemplateChild("Mediator") as ScrollViewerOffsetMediator;
            if (this._scrollViewer == null || this._mediator == null)
            {
                throw new NullReferenceException("ScrollingHost and Mediator must not be null.");
            }

            this.SelectionChanged += OnSelectionChanged;
        }

        private void OnSelectionChanged(object sender, SelectionChangedEventArgs selectionChangedEventArgs)
        {
            this._scrollViewer.ScrollToHorizontalOffset(this._reverseAnimation
                                                                    ? (this._mediator.HorizontalOffset - 1)
                                                                    : (this._mediator.HorizontalOffset + 1));
        }
    }

    /// <summary>
    /// Mediator that forwards Offset property changes on to a ScrollViewer
    /// instance to enable the animation of Horizontal/VerticalOffset.
    /// </summary>
    public class ScrollViewerOffsetMediator : FrameworkElement
    {
        /// <summary>
        /// ScrollViewer instance to forward Offset changes on to.
        /// </summary>
        public ScrollViewer ScrollViewer
        {
            get { return (ScrollViewer)GetValue(ScrollViewerProperty); }
            set { SetValue(ScrollViewerProperty, value); }
        }
        public static readonly DependencyProperty ScrollViewerProperty =
            DependencyProperty.Register(
                "ScrollViewer",
                typeof(ScrollViewer),
                typeof(ScrollViewerOffsetMediator),
                new PropertyMetadata(null, OnScrollViewerChanged));
        private static void OnScrollViewerChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            var mediator = (ScrollViewerOffsetMediator)o;
            var scrollViewer = (ScrollViewer)(e.NewValue);
            if (null != scrollViewer)
            {
                scrollViewer.ScrollToVerticalOffset(mediator.VerticalOffset);
            }
        }

        /// <summary>
        /// VerticalOffset property to forward to the ScrollViewer.
        /// </summary>
        public double VerticalOffset
        {
            get { return (double)GetValue(VerticalOffsetProperty); }
            set { SetValue(VerticalOffsetProperty, value); }
        }
        public static readonly DependencyProperty VerticalOffsetProperty =
            DependencyProperty.Register(
                "VerticalOffset",
                typeof(double),
                typeof(ScrollViewerOffsetMediator),
                new PropertyMetadata(null, OnVerticalOffsetChanged));

        public static void OnVerticalOffsetChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            var mediator = (ScrollViewerOffsetMediator)o;
            if (null != mediator.ScrollViewer)
            {
                mediator.ScrollViewer.ScrollToVerticalOffset((double)(e.NewValue));
            }
        }
        /// <summary>
        /// Multiplier for ScrollableHeight property to forward to the ScrollViewer.
        /// </summary>
        /// <remarks>
        /// 0.0 means "scrolled to top"; 1.0 means "scrolled to bottom".
        /// </remarks>
        public double ScrollableHeightMultiplier
        {
            get { return (double)GetValue(ScrollableHeightMultiplierProperty); }
            set { SetValue(ScrollableHeightMultiplierProperty, value); }
        }

        public static readonly DependencyProperty ScrollableHeightMultiplierProperty =
            DependencyProperty.Register(
                "ScrollableHeightMultiplier",
                typeof(double),
                typeof(ScrollViewerOffsetMediator),
                new PropertyMetadata(null, OnScrollableHeightMultiplierChanged));

        public static void OnScrollableHeightMultiplierChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            var mediator = (ScrollViewerOffsetMediator)o;
            var scrollViewer = mediator.ScrollViewer;
            if (null != scrollViewer)
            {
                scrollViewer.ScrollToVerticalOffset((double)(e.NewValue) * scrollViewer.ScrollableHeight);
            }
        }

        /// <summary>
        /// HorizontalOffset property to forward to the ScrollViewer.
        /// </summary>
        public double HorizontalOffset
        {
            get { return (double)GetValue(HorizontalOffsetProperty); }
            set { SetValue(HorizontalOffsetProperty, value); }
        }
        public static readonly DependencyProperty HorizontalOffsetProperty =
            DependencyProperty.Register(
                "HorizontalOffset",
                typeof(double),
                typeof(ScrollViewerOffsetMediator),
                new PropertyMetadata(null, OnHorizontalOffsetChanged));

        public static void OnHorizontalOffsetChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            var mediator = (ScrollViewerOffsetMediator)o;
            if (null != mediator.ScrollViewer)
            {
                mediator.ScrollViewer.ScrollToHorizontalOffset((double)(e.NewValue));
            }
        }
        /// <summary>
        /// Multiplier for ScrollableWidth property to forward to the ScrollViewer.
        /// </summary>
        /// <remarks>
        /// 0.0 means "scrolled to left"; 1.0 means "scrolled to right".
        /// </remarks>
        public double ScrollableWidthMultiplier
        {
            get { return (double)GetValue(ScrollableWidthMultiplierProperty); }
            set { SetValue(ScrollableWidthMultiplierProperty, value); }
        }

        public static readonly DependencyProperty ScrollableWidthMultiplierProperty =
            DependencyProperty.Register(
                "ScrollableWidthMultiplier",
                typeof(double),
                typeof(ScrollViewerOffsetMediator),
                new PropertyMetadata(null, OnScrollableWidthMultiplierChanged));

        public static void OnScrollableWidthMultiplierChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            var mediator = (ScrollViewerOffsetMediator)o;
            var scrollViewer = mediator.ScrollViewer;
            if (null != scrollViewer)
            {
                scrollViewer.ScrollToHorizontalOffset((double)(e.NewValue) * scrollViewer.ScrollableWidth);
            }
        }
    }
}

And here is the template of the control (as you can see, it’s the same template of the FlipView except that I’ve included the ScroolViewerOffsetMediator):

<Style TargetType="animatedFlipView:AnimatedFlipView">
        <Setter Property="Background"
                Value="Transparent" />
        <Setter Property="BorderThickness"
                Value="0" />
        <Setter Property="TabNavigation"
                Value="Once" />
        <Setter Property="IsTabStop"
                Value="False" />
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility"
                Value="Hidden" />
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility"
                Value="Hidden" />
        <Setter Property="ScrollViewer.IsHorizontalRailEnabled"
                Value="False" />
        <Setter Property="ScrollViewer.IsVerticalRailEnabled"
                Value="False" />
        <Setter Property="ScrollViewer.IsHorizontalScrollChainingEnabled"
                Value="True" />
        <Setter Property="ScrollViewer.IsVerticalScrollChainingEnabled"
                Value="True" />
        <Setter Property="ScrollViewer.IsDeferredScrollingEnabled"
                Value="False" />
        <Setter Property="ScrollViewer.BringIntoViewOnFocusChange"
                Value="True" />
        <Setter Property="ItemsPanel">
            <Setter.Value>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel AreScrollSnapPointsRegular="True"
                                            Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="animatedFlipView:AnimatedFlipView">
                    <Grid>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="FocusStates">
                                <VisualState x:Name="Focused">
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="FocusVisualWhite"
                                                         Storyboard.TargetProperty="Opacity"
                                                         To="1"
                                                         Duration="0" />
                                        <DoubleAnimation Storyboard.TargetName="FocusVisualBlack"
                                                         Storyboard.TargetProperty="Opacity"
                                                         To="1"
                                                         Duration="0" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Unfocused" />
                                <VisualState x:Name="PointerFocused" />
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Border Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                Margin="3">
                            <Border.Resources>
                                <ControlTemplate x:Key="HorizontalNextTemplate"
                                                 TargetType="Button">
                                    <Border x:Name="Root"
                                            Background="{StaticResource FlipViewButtonBackgroundThemeBrush}"
                                            BorderThickness="{StaticResource FlipViewButtonBorderThemeThickness}"
                                            BorderBrush="{StaticResource FlipViewButtonBorderThemeBrush}">
                                        <VisualStateManager.VisualStateGroups>
                                            <VisualStateGroup x:Name="CommonStates">
                                                <VisualState x:Name="Normal" />
                                                <VisualState x:Name="PointerOver">
                                                    <Storyboard>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root"
                                                                                       Storyboard.TargetProperty="Background">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPointerOverBackgroundThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root"
                                                                                       Storyboard.TargetProperty="BorderBrush">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPointerOverBorderThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Arrow"
                                                                                       Storyboard.TargetProperty="Fill">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPointerOverForegroundThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                    </Storyboard>
                                                </VisualState>
                                                <VisualState x:Name="Pressed">
                                                    <Storyboard>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root"
                                                                                       Storyboard.TargetProperty="Background">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPressedBackgroundThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root"
                                                                                       Storyboard.TargetProperty="BorderBrush">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPressedBorderThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Arrow"
                                                                                       Storyboard.TargetProperty="Fill">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPressedForegroundThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                    </Storyboard>
                                                </VisualState>
                                            </VisualStateGroup>
                                        </VisualStateManager.VisualStateGroups>
                                        <Path x:Name="Arrow"
                                              Data="M4.12,0 L9.67,5.47 L4.12,10.94 L0,10.88 L5.56,5.47 L0,0.06 z"
                                              Fill="{StaticResource FlipViewButtonForegroundThemeBrush}"
                                              Width="9.67"
                                              Height="10.94"
                                              Stretch="Fill"
                                              HorizontalAlignment="Center"
                                              VerticalAlignment="Center"
                                              UseLayoutRounding="False" />
                                    </Border>
                                </ControlTemplate>
                                <ControlTemplate x:Key="HorizontalPreviousTemplate"
                                                 TargetType="Button">
                                    <Border x:Name="Root"
                                            Background="{StaticResource FlipViewButtonBackgroundThemeBrush}"
                                            BorderThickness="{StaticResource FlipViewButtonBorderThemeThickness}"
                                            BorderBrush="{StaticResource FlipViewButtonBorderThemeBrush}">
                                        <VisualStateManager.VisualStateGroups>
                                            <VisualStateGroup x:Name="CommonStates">
                                                <VisualState x:Name="Normal" />
                                                <VisualState x:Name="PointerOver">
                                                    <Storyboard>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root"
                                                                                       Storyboard.TargetProperty="Background">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPointerOverBackgroundThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root"
                                                                                       Storyboard.TargetProperty="BorderBrush">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPointerOverBorderThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Arrow"
                                                                                       Storyboard.TargetProperty="Fill">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPointerOverForegroundThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                    </Storyboard>
                                                </VisualState>
                                                <VisualState x:Name="Pressed">
                                                    <Storyboard>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root"
                                                                                       Storyboard.TargetProperty="Background">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPressedBackgroundThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root"
                                                                                       Storyboard.TargetProperty="BorderBrush">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPressedBorderThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Arrow"
                                                                                       Storyboard.TargetProperty="Fill">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPressedForegroundThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                    </Storyboard>
                                                </VisualState>
                                            </VisualStateGroup>
                                        </VisualStateManager.VisualStateGroups>
                                        <Path x:Name="Arrow"
                                              Data="M5.55,0 L9.67,0.06 L4.12,5.47 L9.67,10.88 L5.55,10.94 L0,5.48 z"
                                              Fill="{StaticResource FlipViewButtonForegroundThemeBrush}"
                                              Width="9.67"
                                              Height="10.94"
                                              Stretch="Fill"
                                              HorizontalAlignment="Center"
                                              VerticalAlignment="Center"
                                              UseLayoutRounding="False" />
                                    </Border>
                                </ControlTemplate>
                                <ControlTemplate x:Key="VerticalNextTemplate"
                                                 TargetType="Button">
                                    <Border x:Name="Root"
                                            Background="{StaticResource FlipViewButtonBackgroundThemeBrush}"
                                            BorderThickness="{StaticResource FlipViewButtonBorderThemeThickness}"
                                            BorderBrush="{StaticResource FlipViewButtonBorderThemeBrush}">
                                        <VisualStateManager.VisualStateGroups>
                                            <VisualStateGroup x:Name="CommonStates">
                                                <VisualState x:Name="Normal" />
                                                <VisualState x:Name="PointerOver">
                                                    <Storyboard>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root"
                                                                                       Storyboard.TargetProperty="Background">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPointerOverBackgroundThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root"
                                                                                       Storyboard.TargetProperty="BorderBrush">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPointerOverBorderThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Arrow"
                                                                                       Storyboard.TargetProperty="Fill">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPointerOverForegroundThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                    </Storyboard>
                                                </VisualState>
                                                <VisualState x:Name="Pressed">
                                                    <Storyboard>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root"
                                                                                       Storyboard.TargetProperty="Background">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPressedBackgroundThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root"
                                                                                       Storyboard.TargetProperty="BorderBrush">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPressedBorderThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Arrow"
                                                                                       Storyboard.TargetProperty="Fill">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPressedForegroundThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                    </Storyboard>
                                                </VisualState>
                                            </VisualStateGroup>
                                        </VisualStateManager.VisualStateGroups>
                                        <Path x:Name="Arrow"
                                              Data="M0.06,0 L5.47,5.56 L10.88,0 L10.94,4.12 L5.48,9.67 L0,4.12 z"
                                              Fill="{StaticResource FlipViewButtonForegroundThemeBrush}"
                                              Width="10.94"
                                              Height="9.67"
                                              Stretch="Fill"
                                              HorizontalAlignment="Center"
                                              VerticalAlignment="Center"
                                              UseLayoutRounding="False" />
                                    </Border>
                                </ControlTemplate>
                                <ControlTemplate x:Key="VerticalPreviousTemplate"
                                                 TargetType="Button">
                                    <Border x:Name="Root"
                                            Background="{StaticResource FlipViewButtonBackgroundThemeBrush}"
                                            BorderThickness="{StaticResource FlipViewButtonBorderThemeThickness}"
                                            BorderBrush="{StaticResource FlipViewButtonBorderThemeBrush}">
                                        <VisualStateManager.VisualStateGroups>
                                            <VisualStateGroup x:Name="CommonStates">
                                                <VisualState x:Name="Normal" />
                                                <VisualState x:Name="PointerOver">
                                                    <Storyboard>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root"
                                                                                       Storyboard.TargetProperty="Background">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPointerOverBackgroundThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root"
                                                                                       Storyboard.TargetProperty="BorderBrush">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPointerOverBorderThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Arrow"
                                                                                       Storyboard.TargetProperty="Fill">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPointerOverForegroundThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                    </Storyboard>
                                                </VisualState>
                                                <VisualState x:Name="Pressed">
                                                    <Storyboard>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root"
                                                                                       Storyboard.TargetProperty="Background">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPressedBackgroundThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root"
                                                                                       Storyboard.TargetProperty="BorderBrush">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPressedBorderThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Arrow"
                                                                                       Storyboard.TargetProperty="Fill">
                                                            <DiscreteObjectKeyFrame KeyTime="0"
                                                                                    Value="{StaticResource FlipViewButtonPressedForegroundThemeBrush}" />
                                                        </ObjectAnimationUsingKeyFrames>
                                                    </Storyboard>
                                                </VisualState>
                                            </VisualStateGroup>
                                        </VisualStateManager.VisualStateGroups>
                                        <Path x:Name="Arrow"
                                              Data="M5.63,0 L11.11,5.55 L11.05,9.67 L5.64,4.12 L0.23,9.67 L0.17,5.55 z"
                                              Fill="{StaticResource FlipViewButtonForegroundThemeBrush}"
                                              Width="10.94"
                                              Height="9.67"
                                              Stretch="Fill"
                                              HorizontalAlignment="Center"
                                              VerticalAlignment="Center"
                                              UseLayoutRounding="False" />
                                    </Border>
                                </ControlTemplate>
                            </Border.Resources>
                            <Grid>
                                <ScrollViewer x:Name="ScrollingHost"
                                              VerticalSnapPointsType="MandatorySingle"
                                              HorizontalSnapPointsType="MandatorySingle"
                                              HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
                                              HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
                                              VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
                                              VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
                                              IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
                                              IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
                                              IsHorizontalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsHorizontalScrollChainingEnabled}"
                                              IsVerticalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsVerticalScrollChainingEnabled}"
                                              IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
                                              BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}"
                                              Padding="{TemplateBinding Padding}"
                                              ZoomMode="Disabled"
                                              TabNavigation="{TemplateBinding TabNavigation}"
                                              IsTabStop="False">
                                    <ItemsPresenter />
                                </ScrollViewer>

                                <animatedFlipView:ScrollViewerOffsetMediator x:Name="Mediator"
                                                                             ScrollViewer="{Binding ElementName=ScrollingHost}" />

                                <Button x:Name="PreviousButtonHorizontal"
                                        Template="{StaticResource HorizontalPreviousTemplate}"
                                        Width="70"
                                        Height="40"
                                        IsTabStop="False"
                                        HorizontalAlignment="Left"
                                        VerticalAlignment="Center" />
                                <Button x:Name="NextButtonHorizontal"
                                        Template="{StaticResource HorizontalNextTemplate}"
                                        Width="70"
                                        Height="40"
                                        IsTabStop="False"
                                        HorizontalAlignment="Right"
                                        VerticalAlignment="Center" />
                                <Button x:Name="PreviousButtonVertical"
                                        Template="{StaticResource VerticalPreviousTemplate}"
                                        Width="70"
                                        Height="40"
                                        IsTabStop="False"
                                        HorizontalAlignment="Center"
                                        VerticalAlignment="Top" />
                                <Button x:Name="NextButtonVertical"
                                        Template="{StaticResource VerticalNextTemplate}"
                                        Width="70"
                                        Height="40"
                                        IsTabStop="False"
                                        HorizontalAlignment="Center"
                                        VerticalAlignment="Bottom" />
                            </Grid>
                        </Border>
                        <Rectangle x:Name="FocusVisualWhite"
                                   IsHitTestVisible="False"
                                   Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}"
                                   StrokeEndLineCap="Square"
                                   StrokeDashArray="1,1"
                                   Opacity="0"
                                   StrokeDashOffset="1.5" />
                        <Rectangle x:Name="FocusVisualBlack"
                                   IsHitTestVisible="False"
                                   Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush}"
                                   StrokeEndLineCap="Square"
                                   StrokeDashArray="1,1"
                                   Opacity="0"
                                   StrokeDashOffset="0.5" />
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

For simplicity purpose, I’ve only managed the horizontal changes in the FlipView but it should be really simple to perform the same thing for the vertical changes!

 

Happy coding!

Imagine the following use case: a user copy a file from its Windows desktop (so it’s sent to the clipboard) and he want to be able to perform a paste in your Windows Store application to retrieve the image. This is not a common scenario but after all, it could be helpful for your users.

So here is a way to do it. First, we need to get access to the clipboard, using the Clipboard.getContent method:

var dataPackageView = Windows.ApplicationModel.DataTransfer.Clipboard.getContent();

Then, we are going to check if the clipboard contains some StorageItems and retrieve them (here, StorageItem represent a file that has been copied in the clipboard)

if (dataPackageView.contains(Windows.ApplicationModel.DataTransfer.StandardDataFormats.storageItems)) {
    dataPackageView.getStorageItemsAsync().then(function (items) {
        // TODO
    }
}

Now, we’ll get the properties of the first item and we’ll open it to access to a stream that will allow us to load that stream in a bit array and convert that bit array to a base64 string:

items[0].properties.getImagePropertiesAsync().then(function (imgProps) {
    var height = imgProps.height;
    var width = imgProps.width;

    items[0].openReadAsync().then(function (stream) {
        var inputStream = stream.getInputStreamAt(0);
        var reader = new Windows.Storage.Streams.DataReader(inputStream);
        reader.loadAsync(stream.size).then(function(actualSize) {
            var array = new Array(actualSize);
            reader.readBytes(array);
            reader.close();

            var base64Data = Base64.encode(array);

            // TODO
            }, function(error) {
                console.log(error);
            });
        });
    }, function(error) {
        console.log(error);
});

Here is the code for the Base64.encode method:

var Base64 = {
    encode: function(data) {
        var str = "";
        for (var i = 0; i < data.length; i++)
            str += String.fromCharCode(data[i]);

        return btoa(str).split(/(.{75})/).join("\n").replace(/\n+/g, "\n").trim();
    }
}

You may wonder why I have chosen to use a bit array/base64 string. In fact, this is because the next part of the code will be to load an image using the base64 string

var canvasImage = document.createElement('img');
canvasImage.onerror = function (error) {
    console.log(error);
};

canvasImage.onload = function () {
    // TODO
};

canvasImage.src = "data:" + items[0].contentType + ";base64," + base64Data;

When the image is loaded, we’ll access our HTML5 canvas and draw the image within:

canvasImage.onload = function () {
    var canvas = document.getElementById("canvas");
    canvas.width = width;
    canvas.height = height;

    var ctx = canvas.getContext("2d");
    ctx.drawImage(this, 0, 0, width, height);

    canvasImage = undefined;
};

And voila ! Of course, there are other possibilities (like setting the source of an image that’s already added to the DOM instead of using a Canvas). And even if I’ve used JavaScript code here, we could have easily perform the same thing using C# because, if you are able to access to the file stream, you’re able to perform what you want with it (load it in a BitmapImage for example).

Happy coding!

Microsoft has released recently Windows Azure Mobile Services, a set of tools allowing developers to get backend, authentication and notification for the Windows Store (and Windows Phone) applications.

Activate Windows Azure Mobile Services

The feature is currently in preview so to activate it, you need to go here and activate the feature:

image

For now, the feature is free but you need a valid Azure subscription to use it (thanks to my MSDN account, I’ve been able to set up my Azure account).

Create your first application

Once the feature has been activated, this one is available directly in your management portal. So go to https://manage.windowsazure.com and click on “Mobile Services” to see the list of all the services you’ve created:

image

Here, you can see that I’ve already created a mobile services but let’s take a look at how you can create your own. On the bottom of the screen, click on “New” and click on “Create”:

image

In the screen that appear, you’re asking to indicate the URL of your service (this one ends with “.azure-mobile.net”), the database that you want to use (a new one or a database you’ve already created) and the region. As the feature is still in preview, you’ll notice that there are only 2 regions available: West US and East US:

image

Don’t worry if you’re setting an URL that is already in use: the system will let you know that point:

image

Next, you’re asking the credentials to connect (or create) to the database:

image

Once this is done, you can click on your service and you’re redirected to the Dashboard page, where you can see some stats about usage:

image

image

Manage data

First thing you need to do is to create/add some tables to the database you’ve specified for your mobile service. For that, click on the “Data” tab and click on “Add a table” to create a new table:

image

On the screen that appear, you can create a new table and set the different permissions needed to perform select and CRUD operations:

image

There are 4 kind of permissions, each of them is explained here:

  1. Everyone: This means that any request for the operation against the table is accepted. This option leaves your data wide-open for everyone to access.
  2. Anybody with the Application Key: The application key is required to perform the operation. The application key is distributed with the application. Because this key is not securely distributed, it cannot be considered a security token. To secure access to your mobile service data, you must instead authenticate users before accessing.
  3. Only Authenticated Users: Only authenticated users are permitted to perform the operation. Scripts can be used to further restrict access to tables based on an authenticated user.
  4. Only Scripts and Admins: The operation requires the service master key, which limits the operation only to registered scripts or to administrator accounts.

You may notice that you’ve not specified the columns of the table. You can click on the table name to see its details but even here, on the “Columns” tab, you just see the columns, you’re not able to add them. By default, you don’t need to predefine the schema of tables in your database. Mobile Services automatically adds columns to a table based on the data you insert. To change this dynamic schema behavior, use the Dynamic Schema setting on the Configure tab:

image

Your data are ready, it’s now time to access them through your Windows Store application!

Access to your backend using Windows Store application

Before being able to access your data via Mobile Services, you need to install the Mobile Services SDK (available here). Once this is done, you can start by adding a reference to the SDK:

image

Then, you have to declare a variable, of type MobileServiceClient, that define a way to access to your Mobile Service:

image

The constructor takes 2 parameters:

  1. The URL from the Mobile Service. This one can be found on the left part of the Dashboard screen
  2. The ApplicationKey, which can be found if you click on the “Manage Keys” button:

image

Now, you need to define a class that represent the table you’ve created before. The technique here is quite similar to the one you can use if you use an ORM tool: you define a class for each table of the database. In our case, we need to define the Users class (be careful, the table already have an column named “id‘”):

image

You’re now ready to perform the basic operations . For example, if you want to query the table, just use the following code:

image

The method ToEnumerableAsync will convert the results to an enumerable object. You can also use the method ToCollectionView to get a CollectionView object from the results. The IMobileServiceTable<T> interface contains a lot of useful methods that you can use to get/insert/update/delete data from the Mobile Service:

image

So if you want to insert an item, you need to use the InsertAsync method:

image

Unfortunately, if you execute this code, you’ll encounter the following error:

image

Why are you unauthorized ? To understand this error, just remember the permissions we’ve set for the Users table:

image

So, as you can see, only scripts (server side components) and administrators are allowed to insert data. So how to make the difference between users and admins? Simply go the “Manage Keys” screen and look for the “Master Key”:

image

Previously, to create our MobileServiceClient object, we’ve used the Application Key but if we change it by the Master Key and re-execute the code, all will work fine and going to the table details screen will show you the item correctly added:

image

Here are some code samples to retrieve data:

image

First query will get all users where date of birth is previous to today. Second one use LookupAsync, taking in parameter the index of the item you want to retrieve.

So, as you can see, using Mobile Service is really simple and allow anyone to have a SQL Azure Database as a backend for any Windows Store application. But you can do more and that’s what we’ll see just now!

Execution of scripts during operations

If you go the details page of the table Users, you can see the “Scripts” tab:

image

On this page, you are able to add some JavaScript code that will occur when the selected operation is executed. Each script take some parameters:

  1. insert/update: Take in parameter the item that you want to insert/update, the user who submitted the query and the request, used to execute the operation and to notify the user by sending an response.
  2. del (delete): Take in parameter the id of the item to delete from the database
  3. read: Take in parameter the query that will be executed against the table, , the user who submitted the query and the request, used to execute the operation and to notify the user by sending an response.

For the request object, there are 2 methods that you can use:

  1. execute, that will execute the operation
  2. respond: that will report the response to the user. If you want to return an error to the user, you need to use this method, passing in parameters the error to displayed or the HTTP code and response to display to the user.

For your information, here is the full list of all the HTTP code available:

  1. OK: 200
  2. CREATED: 201
  3. ACCEPTED: 202
  4. NO_CONTENT: 204
  5. BAD_REQUEST: 400
  6. UNAUTHORIZED: 401
  7. FORBIDDEN: 403
  8. NOT_FOUND: 404
  9. CONFLICT: 409
  10. INTERNAL_SERVER_ERROR: 500

For example, if you want to perform a check (server side) of the data submitted, you can do it here:

image

Now, if you try to execute this code:

image

You’ll have the following error:

image

Complete document about server scripts can be found here: http://msdn.microsoft.com/en-US/library/windowsazure/jj554226.

Authenticate users in your Windows Store application

A common (and useful) scenario that need to be implemented in some application is the authentication of users. Thanks to Mobile Services, we can use the infrastructure provided by Microsoft and use it in our Windows Store application to allow connection through Live Services, Facebook, Twitter and Google.

First, you need to register your application on the Windows Store. Go to the Dev Center – Windows Store Apps and click on App name:

image

Type a name for your app in App name, click Reserve app name, and then click Save:

image

Now, in Visual Studio, right-click on your project in Solution Explorer click Store, and then click Associate App with the Store…:

image

Once connected, on the screen entitled “Associate Your App with the Windows Store”, select the app that you registered in step 2, click Next, and then click Associate:

image

image

Doing this steps allow you to update the application manifest to store the required information.

Now, go to the Live Connect Developer Center and, on My applications tab, and click your app in the My applications list:

image

Click Edit settings, then API Settings and make a note of the value of Client secret:

image

In Redirect domain, enter the URL of your mobile service (you can found it on the left your Dashboard) and click Save:

image

image

Go back to the Management Portal, click the Identity tab, enter the Client secret obtained from Windows Store, and click Save:

image

Your Mobile Service and your application are now configured to work with Live Connect: it’s time to add authentication to the app.

Start by download and install the Live SDK for Windows:

image

In the Project menu in Visual Studio, click Add Reference, then expand Windows, click Extensions, check Live SDK, and then click OK:

image

Once this is done, add the following code which help you to log on an user using Live Connect:

image

(Don’t forget to update the Redirect domain URL before to continue).

Finally, add this code that will update the first user of your database:

image

Unfortunately; if you execute the code, you’ll get another Unauthorized error:

image

Indeed, once again, the problem occurs because the Users table is configured to allow update only to authenticate users. So, before calling the UpdateUser method, add the following code which will authenticate the user:

image

Once the Authenticate method is called, the app display a screen asking confirmation to user (for security purpose):

image

After you’ve been successfully authenticated, the update method can be executed without any problems and entry is updated in database.

image

Send push notifications to your Windows Store application

Push notifications are another good technique to make your application feel more “Windows 8 compliant”. Using them with Mobile Services is really simple again. If you have done all previous tasks correctly, just go to Live Connect Developer Center and under API Settings, make a note of the values of Client secret and Package security identifier (SID):

image

In Windows Azure Management Portal, click Mobile Services, click your app and click the Push tab. Enter the Client secret and Package SID values obtained before, and then click Save:

image

Now, you’re ready to add push notifications to your app. First, we need to get a notification channel and store it in the database so add the following code in App.xaml.cs:

image

Then, at the top of the OnLaunched event handler in App.xaml.cs, add the following call to the new AcquirePushChannel method:

image

The channel will be store in the database and, thanks to the technique of dynamic schema, we just need to add the corresponding property to the Users object:

image

Now, just add a new item in the database, and don’t forget to set its Channel property:

image

Depending of the type of notification you want to use, you might need to edit the manifest file to specify if the application is capable to receive Toast notifications or not (in our case, it’s yes):

image

Code in application is finished but, as you can see, we don’t have written any code related to push notifications yet. This is because this part is done on the server side, using the scripts executed during the operations (read/write/delete/update).

Our previous “Insert” script was this one:

image

We’ll modify it to ask the server to send a push notification when the request is executed:

image

As you can see, when the request is executed, we send a Toast notification, the number 4 (which accept up to 3 lines of text). Of course, all others kind of notifications (I mean badge and tile) are available if you need/want them. Just save your script and execute your application: if you have performed all the steps correctly, you should received a notification:

image

Here is a more complex Insert script, which use the Table object to access the number of items in the Users table and push a notification using the value:

image

Executing this script show a new toast notification:

image

And values returns by the read method of the Table object is good:

image

Conclusion

As you can see, Windows Azure Mobile Services is really simple to use and provide a lot of great features. Advanced developers might regrets that they don’t have access to the code of the methods provided but I think it can really useful in some scenarios so don’t hesitate to take a look at it: I’m sure you’ll appreciate it!

 

Happy coding!

Now that you have finally developed your application, you may wonder how this one could help you to get money. There is, at least, 2 possibilities:

  1. Add some fee to get your application
  2. Create a free application that will have ads

The second option is interesting because it does not make sense to buy all applications, particularly if your application use a free service. So let’s take a look at the Microsoft’s solution to get some ads in your Windows 8 applications.

Download the SDK

First thing you need to do is to download the Microsoft Advertising SDK for Windows 8. This one can be found here. Once downloaded, install it and go to the next part (yes, this is probably the most simple part of this tutorial).

Register your application

To display ads in your Windows 8 application, you must first register your application with pubCenter. This allows pubCenter to communicate with your application through the pubCenter API and begin serving ads. So first, create an account to the pubCenter (https://pubcenter.microsoft.com) then:

  1. Click the Setup tab.
  2. Click Applications.
  3. Click Register application.
  4. In the Name box, enter an application name.
  5. In the Device type box, select the type of device (indeed, you can choose Windows 8 or Windows Phone because this is the same system).

image

Once an application is registered, you can begin creating ad units for your application. Don’t forget to note the Application ID that is display on the Application details screen: you’ll need it in your code:

image

Create Ad units

Ad units contain ads displayed in your application. You can create as many as ad units for your application. Here are the steps needed to create your first ad unit:

  1. Click the Setup tab.
  2. Click Ad units.
  3. Click the Windows 8 application tab.
  4. Click Create application ad unit.
  5. In the Ad unit name box, enter the name you want to use for this ad unit.
  6. In the Application box, select the application for this ad unit.
  7. In the Ad unit size box, select the dimensions of the ad unit as it will appear in your application. Note that, on the right part of the screen, you can see a sample preview.
  8. In the Windows 8 App Store categories section, choose one category for the type of advertisements.

image

In the Application code information section, make a note your Ad Unit ID. Once again, you’ll need it in your application code (note that the Application ID is recalled here too in case you miss it).

Use the Ads controls

Your application and ad unit are created, you are now ready to use them in your application code. First, as the controls will communicate with pubCenter using APIs, you need to be sure that Internet is allowed in your application. Double-click on the file Package.appxmanifest and, in Capabilities tab, look to see if Internet (Client) is checked.

image

OK, now, you need to add a reference to the Advertising SDK to be able to use the controls available to you. From the Solution Explorer window, right click References, and then select Add Reference…:

image

Click Windows, and that will expand to show Extensions. Click Extensions, select Microsoft Advertising SDK for Windows 8 (XAML), and then click OK:

image

If you are working on a JavaScript project, the steps are the same except that the reference is named Microsoft Advertising SDK for Windows 8 (JS):

image

Next steps are similar if you are working in XAML or JavaScript but, for simplicity purpose, I’ll cover both technology.

XAML Application

The AdControl can be used directly in your application. You need to add the following namespace before to continue:

xmlns:Ads="using:Microsoft.Advertising.WinRT.UI"

Then, just add the following code:

<Ads:AdControl ApplicationId="XXXXX-XXXX-XXXX-XXXX-XXXXXXX"
               AdUnitId="XXXXXX"
               Height="250"
               Width="250"
               HorizontalAlignment="Center"
               VerticalAlignment="Center" />

As you can see, you need to set the properties ApplicationId and AdUnitId (the ones you have to remember from the steps above) and, if you execute the code, you can see the following results:

image

The AdControl is just a simple ContentControl that use pubCenter APIs to get the ad that need to be displaed. If user click on the ad, he is redirected to the website dedicated to it.

JavaScript Application

The same result can be obtained from a JavaScript Application. After adding the reference, just add the following code:

<script src="/MSAdvertisingJS/ads/ad.js"></script>

Then, you’re now able to create an AdControl using the same technique you use to create a ListView (for example): create a div element and set its data-win-control property to MicrosoftNSJS.Advertising.AdControl:

<div id="adControl" style="position: absolute; top: 53px; left: 0px; width: 250px; height: 250px; z-index: 1"
     data-win-control="MicrosoftNSJS.Advertising.AdControl"
     data-win-options="{applicationId: 'XXXX-XXXX-XXXX-XXXX-XXXXXXX', adUnitId: 'XXXXXX'}">
</div>

Once again, you can see that properties applicationId and adUnitId are set (using the data-win-options property).

The result is quite similar to the XAML version (the image might not be the same because, remember, it’s provided by pubCenter):

image

 

As you can see, this is really easy to use and you can easily integrate it in your applications. For example, if you have a XAML application, just create a DataTemplateSelector:

public class ItemTemplateSelector : DataTemplateSelector
{
    protected override Windows.UI.Xaml.DataTemplate SelectTemplateCore(object item, Windows.UI.Xaml.DependencyObject container)
    {
        var sampleDataItem = item as SampleDataItem;
        if(sampleDataItem != null)
        {
            if(sampleDataItem.UniqueId == "pub")
            {
                return Application.Current.Resources["PubTemplate"] as DataTemplate;
            }
        }

        return Application.Current.Resources["Standard250x250ItemTemplate"] as DataTemplate;
    }
}

Using this code, I can choose the DataTemplate that my GridView will apply to its item.

<GridView x:Name="itemGridView"
          AutomationProperties.AutomationId="ItemGridView"
          AutomationProperties.Name="Grouped Items"
          Grid.RowSpan="2"
          Padding="116,137,40,46"
          ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}"
          ItemTemplateSelector="{StaticResource ItemTemplateSelector}"
          SelectionMode="None"
          IsSwipeEnabled="false"
          IsItemClickEnabled="True"
          ItemClick="ItemView_ItemClick">

Then, if I execute the code, you can see that all the items are correctly loaded as tiles but, for one of them, the tile display an ad:

image

Of course, the size for the tile of the ad is the same as all other tiles but if you create an Ad unit for different size, don’t forget to set up your GridView to use different items sizes.

More about AdControl

Here are some tips about the AdControl.

  1. First, if you want to refresh the ad displayed on screen, you need to set the property IsAutoRefreshEnabled to false. Then, call the Refresh method.
  2. If you want to improve performances when user is scrolling, set the property IsPerformanceScrollingEnabled to true. When the user will scroll, the current ad will temporarily be replaced by a snapshot image of the ad. When the AdControl has stopped scrolling it will revert back to normal behavior.
  3. Calling Suspend method, on the AdControl, suspends the current ad and replaces the current view of the ad with a snapshot of what was currently being rendered. After calling Suspend the AdControl will not automatically refresh, if IsAutoRefreshEnabled=true, and you cannot manually refresh the AdControl until Resume has been called.
  4. If you call the Resume method, it’ll remove the static snapshot of the AdControl and replaces it with the dynamic display.  If IsAutoRefreshEnable is set to true, automatic refresh will resume.

 

Results

To see how much money you’ve earned using the ads in your application, you just need to go in the pubCenter: https://pubcenter.microsoft.com/ReportManagement/Dashboard.aspx

image

Conclusion

As you can see, earning money with Windows 8 applications is really simple. Microsoft Advertising SDK simplify a lot the work for developers. You can set as many ads as you want in you application. You can even use multiple ads on the same screen but just be careful to not use too many ads or your users might don’t appreciate.

 

Happy coding!