Windows 8 FlipView with WebView

Over the last several months, I’ve been working with a client on a Windows 8 app.  The app is basically a book but rather than embedding the pages of the book in the app, the client wants to load the pages dynamically when the app starts and cache them for a period of time.  Since each page of the book has a corresponding html page, the client decided to load the pages into a WebView control.  A good choice since the WebView control can easily render the html content but it also gives the developer a lot of flexibility to inject scripts and manipulate the DOM – which he did but it’s out of the scope of this blog.

Rather than loading all the pages into a single WebView control, the client wanted the user to be able to swipe left and right to change pages.  The FlipView control was the first choice since it supports the swiping behavior but neither of us were sure we could wrap a WebView control with a FlipView control.  After searching the inter-webs for a while, I found a lot of contradictory information.  Some forums say it’s possible but don’t provide good examples while other claim it’s not possible.  I’m here to confirm that it is possible and here’s how:

Step 1:

Open Visual Studio and create a Windows Store app using the language of your choice.  For my project, I chose XAML/C# and the blank app template.

I’m pretty sure Html5/JS will work but I haven’t confirmed.  Sorry.

Step 2:

For simplicity of this blog, I’m not going to load the html pages dynamically from a web backend.  I’ll just add the pages to a folder in the app and load them from there.  I added a folder called, Content.  Under that folder I added 5 pages.  A title page and 4 content pages.

Step 3:

Open the MainPage.xaml file and add the following XAML inside your Grid.

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <FlipView x:Name="HtmlFlipView" 
                  Width="850" 
                  HorizontalAlignment="Center" Background="White">
        </FlipView>
</Grid>

Step 4:

protected override async void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    if (HtmlFlipView == null || HtmlFlipView.Items == null) return;

    HtmlFlipView.Items.Clear();
    for (int i = 0; i < 5; i++)
    {
        var htmlWebView = new WebView();
        string htmlPage = await WrapHtmlPageAsync(string.Format("mobydickpage{0}.html", i));
        htmlWebView.NavigateToString(htmlPage);

        HtmlFlipView.Items.Add(htmlWebView);
    }
}

private async Task<string> ReadLocalFileAsync(string path)
{
    StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(path));
    return await FileIO.ReadTextAsync(file);
}

private async Task<string> WrapHtmlPageAsync(string htmlPage)
{
    const string customStyle =
"body {font-size: 18px;}";

    // Internal content and scripts
    string content = await ReadLocalFileAsync(string.Format("ms-appx:///content/{0}", htmlPage));

    return string.Format("<!DOCTYPE html><html><head><meta charset='UTF-8'><title>Moby Dick</title>" +
        "<style type='text/css'>{0}</style>" +
        "</head>" +
        "<body>" +
        "{1}" +
        "</body>" +
        "</html>", customStyle, content);
}

That’s it!  When the app loads the MainPage view, the OnNavigatedTo event runs.  I added code to iterate for each page; creating a new WebView control and loading the corresponding html page.

There are probably a million better solutions out there but this one demonstrates the point.  It’s entirely possible to create a WebView control inside a FlipView control to achieve a swipe effect between pages.

Advertisements