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) !

A small tip for anyone who look for the information.

Using a custom font in any Windows Store apps (C# / XAML) is easy and the same as you can do in WPF or Silverlight application.

Indeed, the first step is to add the font file to your solution and mark it as “Content” (on the file’s properties). Then, when you want to use your new font, just set the FontFamily property:

 <TextBlock Text="u"
                    FontSize="72"
                    Foreground="Red"
                    FontFamily="Assets/MyNewFont.ttf#My Font Name"/>

As you can see, you just need to point to the right file and add the font name after the # character (this is because a single file can contains multiple fonts so using this syntax, you know exactly which font will be used).

Note that Visual Studio and Expression Blend both support the feature so you’ll be able to see the change directly in the designers.

 

Happy coding!

Windows 8 provide a new Transcoding API that can help you to transcode an audio or video file from one format to another one.

The API is really simple to use and consist of two majors classes:

  1. MediaEncodingProfile, which contains the settings that will determine how the destination file will be transcoded
  2. MediaTranscoder, which will perform the transformation

First, you need to create a profile to indicate how to transcode the file:

var encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.HD1080p);

MediaEncodingProfile contains factory methods like CreateMp4 or CreateWmv. The parameter of the methods gives the target resolution (in our case 1080p).

Next, you can call PrepareFileTranscodeAsync to transcode the file (after checking if the source can really be transcoded):

var prepareTranscodeResult = await transcoder.PrepareFileTranscodeAsync(sourceFile, destinationFile, encodingProfile);

if (prepareTranscodeResult.CanTranscode)
{
    await prepareTranscodeResult.TranscodeAsync();
}

And voila! Again, you can see that the API is very simple and flexible (you can, if you want, load a profile from a file or trim the destination file using the properties TrimStartTime and TrimStopTime!).

For my tests, I’ve worked with a WMV file of 30 seconds for 25Mb. After converted it in MP4 (1080p), the result file was 65Mb (more bigger for more quality) and another conversion to VGA gave a file of 11Mb: as you can see, the result file depend of the quality you decide to use.

So now, you’re ready to create you own audio/video editor in a cool Windows Store app!

 

Happy coding!

Windows Azure Mobile Services is a awesome product that will help you to deliver great apps using a Windows Azure backend.

One of the feature I like is the possibility to send push notifications to modify tiles in just few lines of code. There is just a small drawback to this technique: as the queue notification must be enable from the client code, you won’t be able to get animated tiles.

But (as there is always a “but” ;), the next part of this post will provide you a simple but useful technique to get animated tiles for you Windows Store app.

In fact, instead of of send a classic notification, we’ll use the sendRaw method of the wns object to send a Raw notification. As a reminder, a raw notification is a notification that’s not displayed on the screen: as a developer, your code is notified that the notification is coming and you have to perform what you want/need.

So first, you have to create your server script (here is mine as an example):

var LASTEST_QUOTES_NUMBER = 5;

var payload;
var idx;

function cleanChannels(callback) {
    var channelsTable  = tables.getTable('Channel');

    channelsTable.read({
        success: function(channels) {
            if(channels.length > 0) {
                channels.forEach(function(channel){
                    if(channel.expirationTime < new Date()){
                        channelsTable.del(channel.id);
                    }
                })
            }

            if(callback) {
                callback();
            }
        }
    })
}

function preparePayload(movie, quote){
     payload += "<QuoteWithMovie>" +
                    "<Movie Title=\"" + movie.title + "\" FrontCover=\"" + movie.poster_path + "\" BackCover=\"" + movie.backdrop_path + "\" />" +
                    "<Quote Text=\"" + quote.text.substring(100) + "\" />" +
                "</QuoteWithMovie>";

    idx++;

    if(idx == LASTEST_QUOTES_NUMBER) {

        payload += "</Results>";

        cleanChannels(function() {
            var channelsTable  = tables.getTable('Channel');

            channelsTable.read({
                success: function(channels) {
                    if(channels.length > 0) {
                        for (var i = 0; i < channels.length; i++) {
                            var channel = channels[i];

                            push.wns.sendRaw(channel.uri, payload);
                        }
                    }
                }
            });
        });
    }
}

function sendLatestQuotes() {

    payload = "";
    idx = 0;

    var moviesTable = tables.getTable('Movie');
    var quotesTable = tables.getTable('Quote');

    quotesTable.where({ ispublished: true })
    .orderBy('date')
    .take(LASTEST_QUOTES_NUMBER)
    .read({
        success: function(latestQuotes) {
            payload += "<Results>";

            latestQuotes.forEach(function(quote) {
                moviesTable.where({ movieid: quote.movieid })
                .read({
                    success: function(movies) {
                       preparePayload(movies[0], quote);
                    }
                })
            })
        }
    })
}

As you can see, the code is pretty simple: a XML payload is construct from some database records and, when I have the number of notification I want (5 because notification queuing allow you to switch up to 5 notifications), I send a raw notification, using the payload constructed before.

On the client side, the code use the PushNotificationReceived event to be notified and, if a raw notification is coming, the code use the content (the XML payload) to update the tile:

 var currentChannel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
currentChannel.PushNotificationReceived += async (sender, args) =>
{
    if (args.NotificationType == PushNotificationType.Raw && args.RawNotification != null)
    {
        await MainTileUpdateTask.UpdateMainTileAsync(args.RawNotification.Content);

        // The raw notification should not be passed to its background task
        args.Cancel = true;
    }
};

The code to update the tile and animate it is dedicated to your application but, for you records, here is the one I’m using:

internal static async Task UpdateMainTile(string content)
{
    _isUpdatingTile = true;

    var tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication();
    tileUpdater.EnableNotificationQueue(true);

    tileUpdater.Clear();

    var xElement = XElement.Parse(content);
    var quotesWithMovies = from q in xElement.Elements("QuoteWithMovie")
                                            let movie = q.Element("Movie")
                                            let quote = q.Element("Quote")
                                            select new QuoteWithMovie
                                            {
                                                  MovieTitle = movie.Attribute("Title").Value,
                                                  FrontCover = movie.Attribute("FrontCover").Value,
                                                  BackCover = movie.Attribute("BackCover").Value,
                                                  Text = quote.Attribute("Text").Value
                                            };

    var quoteWithMovies = quotesWithMovies as IList<QuoteWithMovie> ?? quotesWithMovies.ToList();
    if (quoteWithMovies.Any())
    {
        for (int index = 0; index < quoteWithMovies.Count; index++)
        {
            var quote = quoteWithMovies[index];

            var frontCoverFileFullUrl =
            await MoviesService.Current.GetFullCoverImageUrlAsync(quote.FrontCover, "w154");
            var backCoverFileFullUrl =
            await MoviesService.Current.GetFullCoverImageUrlAsync(quote.BackCover, "w300");

            var squareImageFilename = string.Format("Square_{0}.jpg", index);
            var wideImageFilename = string.Format("Wide_{0}.jpg", index);

            FileHelpers.DownloadFile(ApplicationData.Current.LocalFolder, squareImageFilename,
            frontCoverFileFullUrl);

            FileHelpers.DownloadFile(ApplicationData.Current.LocalFolder, wideImageFilename,
            backCoverFileFullUrl);

            var wideTile = Core.UI.Notifications.TileContentFactory.CreateTileWideImageAndText01();
            wideTile.Branding = TileBranding.None;
            wideTile.RequireSquareContent = false;
            wideTile.Image.Src = string.Format("ms-appdata:///local/{0}", wideImageFilename);
            wideTile.Image.Alt = quote.MovieTitle;
            wideTile.TextCaptionWrap.Text = quote.Text;

            var squareTile = Core.UI.Notifications.TileContentFactory.CreateTileSquareImage();
            squareTile.Branding = TileBranding.None;
            squareTile.Image.Src = string.Format("ms-appdata:///local/{0}", squareImageFilename);
            squareTile.Image.Alt = quote.MovieTitle;

            var wideTileNotification = wideTile.CreateNotification();
            var squareTileNotification = squareTile.CreateNotification();

             tileUpdater.Update(wideTileNotification);
             tileUpdater.Update(squareTileNotification);
         }
    }

    _isUpdatingTile = false;
}

The might be others techniques to perform the same results but I like this one for one reason: raw notification can be received by BackgroundTask!

So if you add a BackgroundTask (which set its trigger to PushNotificationTrigger) and put you server code in a Mobile Services Scheduler, you’ll be able to update the tile even if the app is not running!

 

Happy coding!

Indeed, there are no Size or Length properties exposed by the StorageFile class. So a simple but useful trick is to read the content of the file as a Buffer and access to the Length property to access the basic properties of the file and use the Size property:

public async static Task<ulong> GetFileSizeAsync(this IStorageFile file)
{
    var properties = await file.GetBasicPropertiesAsync();

    return properties.Size;
}

Happy coding !

During my last holidays, I’ve started to work on a new Windows 8 project (more details on that later) that use Windows Azure Mobile Services as a backend.

During the development, I’ve encountered the following issue which, I suppose, is a bug that will be fixed later.

On my application, I used the following code:

var allItems = await ServiceClient.GetTable<Items>().Where(i => i.IsPublished).ToListAsync();

return allItems;

Unfortunately, this code thrown, every time, the following error:

image

After taking a look in Fiddler, I found the problem:

image

As you may know, Mobile Services use REST to access data on the server and the following REST query does not seem to be valid because there is no query operator (like eq for equal, etc.) and no value. So, I’ve tried to modify my code like this:

var allItems = await ServiceClient.GetTable<Items>().Where(i => i.IsPublished == true).ToListAsync();

return allItems;

As you can see, I’ve just append “== true” to the Where clause and all seems to work like a charm. Indeed, no exception was rise and, looking at the REST query, we can see that all is OK:

image

 

Happy coding!

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!

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!