Condividi tramite


Blog reader complete code (Windows Store apps using C#/VB and XAML)

[ This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation ]

This topic provides the complete code sample used in the tutorial Part 5: Create a blog reader.

Important  This tutorial is intended for use with Microsoft Visual Studio 2012 and Windows 8. Parts of it will not work correctly with Microsoft Visual Studio 2013 and Windows 8.1.

 

This topic contains these sections:

  • Technologies
  • Requirements
  • View the code (XAML)

Download location

This sample is not available for download.

Technologies

Programming languages C#, Visual Basic .NET
Programming models Windows Runtime

Requirements

Minimum supported client Windows 8
Minimum supported server Windows Server 2012
Minimum required SDK Microsoft Visual Studio Express 2012 for Windows 8

View the code (XAML)

App.xaml

<Application
    x:Class="WindowsBlogReader.App"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WindowsBlogReader">

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>

                <!-- 
                    Styles that define common aspects of the platform look and feel
                    Required by Visual Studio project and item templates
                 -->
                <ResourceDictionary Source="Common/StandardStyles.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            
            <local:FeedDataSource x:Key="feedDataSource"/>
            <local:DateConverter x:Key="dateConverter"/>

            <SolidColorBrush x:Key="WindowsBlogBackgroundBrush" Color="#FF0A2562"/>
            <Style x:Key="WindowsBlogLayoutRootStyle" 
                           TargetType="Panel" 
                           BasedOn="{StaticResource LayoutRootStyle}">
                <Setter Property="Background" 
                                Value="{StaticResource WindowsBlogBackgroundBrush}"/>
            </Style>

            <ControlTemplate x:Key="DateBlockTemplate">
                <Canvas Height="86" Width="86"  Margin="8,8,0,8" 
                        HorizontalAlignment="Left" VerticalAlignment="Top">
                    <TextBlock TextTrimming="WordEllipsis" TextWrapping="NoWrap" 
                                       Width="Auto" Height="Auto" Margin="8,0,4,0" 
                                       FontSize="32" FontWeight="Bold">
                        <TextBlock.Text>
                            <Binding Path="PubDate" Converter="{StaticResource dateConverter}" 
                                     ConverterParameter="month"  />
                        </TextBlock.Text>
                    </TextBlock>

                    <TextBlock TextTrimming="WordEllipsis" TextWrapping="Wrap" 
                                       Width="40" Height="Auto" Margin="8,0,0,0" 
                                       FontSize="34" FontWeight="Bold" Canvas.Top="36">
                        <TextBlock.Text>
                            <Binding Path="PubDate" Converter="{StaticResource dateConverter}" 
                                     ConverterParameter="day"  />
                        </TextBlock.Text>
                    </TextBlock>
                    <Line Stroke="White" StrokeThickness="2" X1="54" Y1="46" X2="54" Y2="80" />

                    <TextBlock TextWrapping="Wrap" 
                               Width="20" Height="Auto" 
                               FontSize="{StaticResource ControlContentThemeFontSize}" 
                               Canvas.Top="42" Canvas.Left="60">
                        <TextBlock.Text>
                            <Binding Path="PubDate" Converter="{StaticResource dateConverter}" 
                                     ConverterParameter="year"  />
                        </TextBlock.Text>
                    </TextBlock>
                </Canvas>
            </ControlTemplate>

            <SolidColorBrush x:Key="ListViewItemSelectedBackgroundThemeBrush" Color="#FF465985"/>
            <SolidColorBrush x:Key="ListViewItemSelectedPointerOverBackgroundThemeBrush" Color="#FF384A72"/>
            <SolidColorBrush x:Key="ListViewItemSelectedPointerOverBorderThemeBrush" Color="#FF384A72" />
            
        </ResourceDictionary>
    </Application.Resources>
</Application>

App.xaml.cs/vb

using System;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

// The Blank Application template is documented at https://go.microsoft.com/fwlink/p/?LinkID=234227

namespace WindowsBlogReader
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default Application class.
    /// </summary>
    sealed partial class App : Application
    {
        /// <summary>
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            this.InitializeComponent();
            this.Suspending += OnSuspending;
        }

        /// <summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used when the application is launched to open a specific file, to display
        /// search results, and so forth.
        /// </summary>
        /// <param name="args">Details about the launch request and process.</param>
        protected async override void OnLaunched(LaunchActivatedEventArgs args)
        {
            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();
                WindowsBlogReader.Common.SuspensionManager.RegisterFrame(rootFrame, "AppFrame");

                var connectionProfile = Windows.Networking.Connectivity.NetworkInformation.GetInternetConnectionProfile();
                if (connectionProfile != null)
                {
                    FeedDataSource feedDataSource = (FeedDataSource)App.Current.Resources["feedDataSource"];
                    if (feedDataSource != null)
                    {
                        if (feedDataSource.Feeds.Count == 0)
                        {
                            await feedDataSource.GetFeedsAsync();
                        }
                    }
                }
                else
                {
                    var messageDialog = new Windows.UI.Popups.MessageDialog("An internet connection is needed to download feeds. Please check your connection and restart the app.");
                    var result = messageDialog.ShowAsync();
                }

                if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    //TODO: Load state from previously suspended application
                    await WindowsBlogReader.Common.SuspensionManager.RestoreAsync();
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                if (!rootFrame.Navigate(typeof(ItemsPage), args.Arguments))
                {
                    throw new Exception("Failed to create initial page");
                }
            }
            // Ensure the current window is active
            Window.Current.Activate();
        }

        /// <summary>
        /// Invoked when application execution is being suspended.  Application state is saved
        /// without knowing whether the application will be terminated or resumed with the contents
        /// of memory still intact.
        /// </summary>
        /// <param name="sender">The source of the suspend request.</param>
        /// <param name="e">Details about the suspend request.</param>
        private async void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();
            //TODO: Save application state and stop any background activity
            await WindowsBlogReader.Common.SuspensionManager.SaveAsync();
            deferral.Complete();
        }
    }
}
' The Blank Application template is documented at https://go.microsoft.com/fwlink/p/?LinkID=234227

''' <summary>
''' Provides application-specific behavior to supplement the default Application class.
''' </summary>
NotInheritable Class App
    Inherits Application

    ''' <summary>
    ''' Invoked when the application is launched normally by the end user.  Other entry points
    ''' will be used when the application is launched to open a specific file, to display
    ''' search results, and so forth.
    ''' </summary>
    ''' <param name="args">Details about the launch request and process.</param>
    Protected Overrides Async Sub OnLaunched(args As Windows.ApplicationModel.Activation.LaunchActivatedEventArgs)
        Dim rootFrame As Frame = Window.Current.Content

        ' Do not repeat app initialization when the Window already has content,
        ' just ensure that the window is active

        If rootFrame Is Nothing Then
            ' Create a Frame to act as the navigation context and navigate to the first page
            rootFrame = New Frame()
            Common.SuspensionManager.RegisterFrame(rootFrame, "AppFrame")

            ' Add this code after "rootFrame = new Frame()"
            Dim connectionProfile = Windows.Networking.Connectivity.NetworkInformation.GetInternetConnectionProfile()
            If connectionProfile IsNot Nothing Then
                Dim feedDataSource = DirectCast(App.Current.Resources("feedDataSource"), FeedDataSource)
                If feedDataSource IsNot Nothing Then
                    If feedDataSource.Feeds.Count = 0 Then
                        Await feedDataSource.GetFeedsAsync()
                    End If
                End If
            Else
                Dim messageDialog = New Windows.UI.Popups.MessageDialog("An internet connection is needed to download feeds. Please check your connection and restart the app.")
                Dim result = messageDialog.ShowAsync()
            End If

            If args.PreviousExecutionState = ApplicationExecutionState.Terminated Then
                ' TODO: Load state from previously suspended application
                Await Common.SuspensionManager.RestoreAsync()
            End If
            ' Place the frame in the current Window
            Window.Current.Content = rootFrame
        End If
        If rootFrame.Content Is Nothing Then
            ' When the navigation stack isn't restored navigate to the first page,
            ' configuring the new page by passing required information as a navigation
            ' parameter
            If Not rootFrame.Navigate(GetType(ItemsPage), args.Arguments) Then
                Throw New Exception("Failed to create initial page")
            End If
        End If

        ' Ensure the current window is active
        Window.Current.Activate()
    End Sub

    ''' <summary>
    ''' Invoked when application execution is being suspended.  Application state is saved
    ''' without knowing whether the application will be terminated or resumed with the contents
    ''' of memory still intact.
    ''' </summary>
    ''' <param name="sender">The source of the suspend request.</param>
    ''' <param name="e">Details about the suspend request.</param>
    Private Async Sub OnSuspending(sender As Object, e As SuspendingEventArgs) Handles Me.Suspending
        Dim deferral As SuspendingDeferral = e.SuspendingOperation.GetDeferral()
        ' TODO: Save application state and stop any background activity
        Await Common.SuspensionManager.SaveAsync()
        deferral.Complete()
    End Sub
End Class

ItemsPage.xaml

<common:LayoutAwarePage
    x:Name="pageRoot"
    x:Class="WindowsBlogReader.ItemsPage"
    DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WindowsBlogReader"
    xmlns:common="using:WindowsBlogReader.Common"
    xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Page.Resources>

        <!-- Collection of items displayed by this page -->
        <CollectionViewSource
            x:Name="itemsViewSource"
            Source="{Binding Items}"/>

        <!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
        <x:String x:Key="AppName">Windows Team Blogs</x:String>

        <!-- light blue -->
        <SolidColorBrush x:Key="BlockBackgroundBrush" Color="#FF557EB9"/>

        <!-- Grid Styles -->
        <Style x:Key="GridTitleTextStyle" TargetType="TextBlock" 
               BasedOn="{StaticResource BasicTextStyle}">
            <Setter Property="FontSize" Value="26.667"/>
            <Setter Property="Margin" Value="12,0,12,2"/>
        </Style>

        <Style x:Key="GridDescriptionTextStyle" TargetType="TextBlock" 
               BasedOn="{StaticResource BasicTextStyle}">
            <Setter Property="VerticalAlignment" Value="Bottom"/>
            <Setter Property="Margin" Value="12,0,12,60"/>
        </Style>

        <DataTemplate x:Key="DefaultGridItemTemplate">
            <Grid HorizontalAlignment="Left" Width="250" Height="250">
                <Border Background="{StaticResource BlockBackgroundBrush}" />
                <TextBlock Text="{Binding Title}" 
                           Style="{StaticResource GridTitleTextStyle}"/>
                <TextBlock Text="{Binding Description}" 
                           Style="{StaticResource GridDescriptionTextStyle}" />
                <StackPanel VerticalAlignment="Bottom" Orientation="Horizontal"
                        Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}">
                    <TextBlock Text="Last Updated" Margin="12,4,0,8" Height="42"/>
                    <TextBlock Text="{Binding PubDate, Converter={StaticResource dateConverter}}" 
                               Margin="12,4,12,8" />
                </StackPanel>
            </Grid>
        </DataTemplate>

        <!-- Used in Snapped view -->
        <DataTemplate x:Key="NarrowListItemTemplate">
            <Grid Height="80">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Border Background="{StaticResource BlockBackgroundBrush}" 
                        Width="80" Height="80" />
                <ContentControl Template="{StaticResource DateBlockTemplate}" 
                                Margin="-12,-12,0,0"/>
                <StackPanel Grid.Column="1" HorizontalAlignment="Left" 
                            Margin="12,8,0,0">
                    <TextBlock Text="{Binding Title}" MaxHeight="56" TextWrapping="Wrap"/>
                </StackPanel>
            </Grid>
        </DataTemplate>
    </Page.Resources>

    <!--
        This grid acts as a root panel for the page that defines two rows:
        * Row 0 contains the back button and page title
        * Row 1 contains the rest of the page layout
    -->
    <Grid Style="{StaticResource WindowsBlogLayoutRootStyle}">
        <Grid.RowDefinitions>
            <RowDefinition Height="140"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!-- Horizontal scrolling grid used in most view states -->
        <GridView
            x:Name="itemGridView"
            AutomationProperties.AutomationId="ItemsGridView"
            AutomationProperties.Name="Items"
            TabIndex="1"
            Grid.RowSpan="2"
            Padding="116,136,116,46"
            ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
            ItemTemplate="{StaticResource DefaultGridItemTemplate}"
            SelectionMode="None"
            IsSwipeEnabled="false" IsItemClickEnabled="True" ItemClick="ItemView_ItemClick"/>

        <!-- Vertical scrolling list only used when snapped -->
        <ListView
            x:Name="itemListView"
            AutomationProperties.AutomationId="ItemsListView"
            AutomationProperties.Name="Items"
            TabIndex="1"
            Grid.Row="1"
            Visibility="Collapsed"
            Margin="0,-10,0,0"
            Padding="10,0,0,60"
            ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
            ItemTemplate="{StaticResource NarrowListItemTemplate}"
            SelectionMode="None"
            IsSwipeEnabled="false" IsItemClickEnabled="True" ItemClick="ItemView_ItemClick"/>

        <!-- Back button and page title -->
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Button x:Name="backButton" Click="GoBack" 
                    IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" 
                    Style="{StaticResource BackButtonStyle}"/>
            <TextBlock x:Name="pageTitle" Grid.Column="1" Text="{StaticResource AppName}" 
                       IsHitTestVisible="false" 
                       Style="{StaticResource PageHeaderTextStyle}"/>
        </Grid>

        <VisualStateManager.VisualStateGroups>

            <!-- Visual states reflect the application's view state -->
            <VisualStateGroup x:Name="ApplicationViewStates">
                <VisualState x:Name="FullScreenLandscape"/>
                <VisualState x:Name="Filled"/>

                <!-- The entire page respects the narrower 100-pixel margin convention for portrait -->
                <VisualState x:Name="FullScreenPortrait">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" 
                                                       Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" 
                                                    Value="{StaticResource PortraitBackButtonStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemGridView" 
                                                       Storyboard.TargetProperty="Padding">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="96,136,86,56"/>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>

                <!--
                    The back button and title have different styles when snapped, 
                    and the list representation is substituted
                    for the grid displayed in all other view states
                -->
                <VisualState x:Name="Snapped">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" 
                                                       Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" 
                                                    Value="{StaticResource SnappedBackButtonStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" 
                                                       Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" 
                                                    Value="{StaticResource SnappedPageHeaderTextStyle}"/>
                        </ObjectAnimationUsingKeyFrames>

                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView"
                                                       Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemGridView" 
                                                       Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>
</common:LayoutAwarePage>

ItemsPage.xaml.cs/vb

using System;
using System.Collections.Generic;
using Windows.UI.Xaml.Controls;

// The Items Page item template is documented at https://go.microsoft.com/fwlink/p/?LinkID=234233

namespace WindowsBlogReader
{
    /// <summary>
    /// A page that displays a collection of item previews.  In the Split Application this page
    /// is used to display and select one of the available groups.
    /// </summary>
    public sealed partial class ItemsPage : WindowsBlogReader.Common.LayoutAwarePage
    {
        public ItemsPage()
        {
            this.InitializeComponent();
        }

        /// <summary>
        /// Populates the page with content passed during navigation.  Any saved state is also
        /// provided when recreating a page from a prior session.
        /// </summary>
        /// <param name="navigationParameter">The parameter value passed to
        /// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested.
        /// </param>
        /// <param name="pageState">A dictionary of state preserved by this page during an earlier
        /// session.  This will be null the first time a page is visited.</param>
        protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
        {
            // TODO: Assign a bindable collection of items to this.DefaultViewModel["Items"]
            FeedDataSource feedDataSource = (FeedDataSource)App.Current.Resources["feedDataSource"];

            if (feedDataSource != null)
            {
                this.DefaultViewModel["Items"] = feedDataSource.Feeds;
            }
        }

        private void ItemView_ItemClick(object sender, ItemClickEventArgs e)
        {
            // Navigate to the split page, configuring the new page
            // by passing the title of the clicked item as a navigation parameter
            if (e.ClickedItem != null)
            {
                string title = ((FeedData)e.ClickedItem).Title;
                this.Frame.Navigate(typeof(SplitPage), title);
            }
        }
    }
}
' The Items Page item template is documented at https://go.microsoft.com/fwlink/p/?LinkID=234233

''' <summary>
''' A page that displays a collection of item previews.  In the Split Application this page
''' is used to display and select one of the available groups.
''' </summary>
Public NotInheritable Class ItemsPage
    Inherits Common.LayoutAwarePage

    ''' <summary>
    ''' Populates the page with content passed during navigation.  Any saved state is also
    ''' provided when recreating a page from a prior session.
    ''' </summary>
    ''' <param name="navigationParameter">The parameter value passed to <see cref="Frame.Navigate"/>
    ''' when this page was initially requested.
    ''' </param>
    ''' <param name="pageState">A dictionary of state preserved by this page during an earlier
    ''' session.  This will be null the first time a page is visited.</param>
    Protected Overrides Sub LoadState(navigationParameter As Object, pageState As Dictionary(Of String, Object))
        ' TODO: Assign a bindable collection of items to Me.DefaultViewModel("Items")
        Dim feedDataSource = DirectCast(App.Current.Resources("feedDataSource"), FeedDataSource)
        If feedDataSource IsNot Nothing Then
            Me.DefaultViewModel("Items") = feedDataSource.Feeds
        End If

    End Sub

    Private Sub ItemView_ItemClick(sender As Object, e As ItemClickEventArgs) _
        Handles itemGridView.ItemClick, itemListView.ItemClick
        ' Navigate to the split page, configuring the new page
        ' by passing the title of the clicked item as a navigation parameter
        If e.ClickedItem IsNot Nothing Then
            Dim title = (DirectCast(e.ClickedItem, FeedData)).Title
            Me.Frame.Navigate(GetType(SplitPage), title)
        End If
    End Sub
End Class

SplitPage.xaml

<common:LayoutAwarePage
    x:Name="pageRoot"
    x:Class="WindowsBlogReader.SplitPage"
    DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WindowsBlogReader"
    xmlns:common="using:WindowsBlogReader.Common"
    xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Page.Resources>
        <Style x:Key="WebViewAppBarButtonStyle" TargetType="Button" 
           BasedOn="{StaticResource AppBarButtonStyle}">
            <Setter Property="AutomationProperties.AutomationId" Value="WebViewAppBarButton"/>
            <Setter Property="AutomationProperties.Name" Value="View Web Page"/>
            <Setter Property="Content" Value="&#xE12B;"/>
        </Style>

        <Storyboard x:Name="PopInStoryboard">
            <PopInThemeAnimation  Storyboard.TargetName="contentViewBorder" 
                              FromHorizontalOffset="400"/>
        </Storyboard>

        <!-- Collection of items displayed by this page -->
        <CollectionViewSource
            x:Name="itemsViewSource"
            Source="{Binding Items}"/>

        <DataTemplate x:Key="DefaultListItemTemplate">
            <Grid Height="110" Margin="6">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Border Background="#FF6BBD46" Width="110" Height="110">
                    <ContentControl Template="{StaticResource DateBlockTemplate}" />
                </Border>
                <!--<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="110" Height="110">
                    <Image Source="{Binding Image}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
                </Border>-->
                <StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0">
                    <TextBlock Text="{Binding Title}" FontSize="26.667" TextWrapping="Wrap"
                               MaxHeight="72" Foreground="#FFFE5815" />
                    <TextBlock Text="{Binding Author}" FontSize="18.667" />
                    <!--<TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextStyle}" TextWrapping="NoWrap"/>
                    <TextBlock Text="{Binding Author}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/>
                    <TextBlock Text="{Binding PubDate}" Style="{StaticResource BodyTextStyle}" MaxHeight="60"/>-->
                </StackPanel>
            </Grid>
        </DataTemplate>
        
        <!-- green -->
        <SolidColorBrush x:Key="BlockBackgroundBrush" Color="#FF6BBD46"/>
        
        <!-- Used in Filled and Snapped views -->
        <DataTemplate x:Key="NarrowListItemTemplate">
            <Grid Height="80">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Border Background="{StaticResource BlockBackgroundBrush}" 
                        Width="80" Height="80"/>
                <ContentControl Template="{StaticResource DateBlockTemplate}" 
                                Margin="-12,-12,0,0"/>
                <StackPanel Grid.Column="1" HorizontalAlignment="Left" 
                            Margin="12,8,0,0">
                    <TextBlock Text="{Binding Title}" MaxHeight="56" 
                               Foreground="#FFFE5815" TextWrapping="Wrap"/>
                    <TextBlock Text="{Binding Author}" FontSize="12" />
                </StackPanel>
            </Grid>
        </DataTemplate>
    </Page.Resources>

    <Page.TopAppBar>
        <AppBar Padding="10,0,10,0" Background="#F20A2562">
            <Grid>
                <Button Click="ViewDetail_Click" HorizontalAlignment="Right" 
                    Style="{StaticResource WebViewAppBarButtonStyle}"/>
            </Grid>
        </AppBar>
    </Page.TopAppBar>
    <!--
        This grid acts as a root panel for the page that defines two rows:
        * Row 0 contains the back button and page title
        * Row 1 contains the rest of the page layout
    -->
    <Grid Style="{StaticResource WindowsBlogLayoutRootStyle}">
        <Grid.RowDefinitions>
            <RowDefinition Height="140"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition x:Name="primaryColumn" Width="610"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <!-- Back button and page title -->
        <Grid x:Name="titlePanel" Grid.ColumnSpan="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Button
                x:Name="backButton"
                Click="GoBack"
                IsEnabled="{Binding DefaultViewModel.CanGoBack, ElementName=pageRoot}"
                Style="{StaticResource BackButtonStyle}"/>
            <TextBlock x:Name="pageTitle" Grid.Column="1" Text="{Binding Feed.Title}" 
                       Style="{StaticResource PageHeaderTextStyle}" />
        </Grid>

        <!-- Vertical scrolling item list -->
        <ListView
            x:Name="itemListView"
            AutomationProperties.AutomationId="ItemsListView"
            AutomationProperties.Name="Items"
            TabIndex="1"
            Grid.Row="1"
            Margin="-10,-10,0,0"
            Padding="120,0,0,60"
            ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
            IsSwipeEnabled="False"
            SelectionChanged="ItemListView_SelectionChanged"
            ItemTemplate="{StaticResource DefaultListItemTemplate}"/>

        <!-- Details for selected item -->
        <ScrollViewer
            x:Name="itemDetail"
            AutomationProperties.AutomationId="ItemDetailScrollViewer"
            Grid.Column="1"
            Grid.Row="1"
            Padding="70,0,120,0"
            DataContext="{Binding SelectedItem, ElementName=itemListView}"
            Style="{StaticResource VerticalScrollViewerStyle}">

            <Grid x:Name="itemDetailGrid">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>

                <TextBlock x:Name="itemTitle" Text="{Binding Title}" 
                           Style="{StaticResource SubheaderTextStyle}"/>
                <Border x:Name="contentViewBorder" BorderBrush="Gray" BorderThickness="2" 
                        Grid.Row="1" Margin="0,15,0,20">
                    <Grid>
                        <WebView x:Name="contentView" NavigationCompleted="contentView_NavigationCompleted" />
                        <Rectangle x:Name="contentViewRect" />
                    </Grid>
                </Border>
            </Grid>
        </ScrollViewer>

        <VisualStateManager.VisualStateGroups>
            <!-- Visual states reflect the application's view state -->
            <VisualStateGroup x:Name="ApplicationViewStates">
                <VisualState x:Name="FullScreenLandscapeOrWide"/>

                <!-- Filled uses a simpler list format in a narrower column -->
                <VisualState x:Name="FilledOrNarrow">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="primaryColumn" Storyboard.TargetProperty="Width">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="420"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="ItemTemplate">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource NarrowListItemTemplate}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="Padding">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="60,0,66,0"/>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>

                <!--
                    The page respects the narrower 100-pixel margin convention for portrait, and the page
                    initially hides details to show only the list of items
                -->
                <VisualState x:Name="FullScreenPortrait">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PortraitBackButtonStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="Padding">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="100,0,90,60"/>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>

                <!--
                    When an item is selected in portrait the details display requires more extensive changes:
                     * Hide the master list and the column is was in
                     * Move item details down a row to make room for the title
                     * Move the title directly above the details
                     * Adjust margins and padding for details
                 -->
                <VisualState x:Name="FullScreenPortrait_Detail">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PortraitBackButtonStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="primaryColumn" Storyboard.TargetProperty="Width">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="(Grid.Row)">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="(Grid.RowSpan)">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="titlePanel" Storyboard.TargetProperty="(Grid.Column)">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetailGrid" Storyboard.TargetProperty="Margin">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="0,0,0,60"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="Padding">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="100,0,90,0"/>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>

                <!--
                    The back button and title have different styles when snapped, and the page
                    initially hides details to show only the list of items
                -->
                <VisualState x:Name="Snapped">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedBackButtonStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedPageHeaderTextStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="primaryColumn" Storyboard.TargetProperty="Width">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="320"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="ItemTemplate">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource NarrowListItemTemplate}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="Padding">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="20,0,0,0"/>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>

                <!--
                    When snapped and an item is selected the details display requires more extensive changes:
                     * Hide the master list and the column is was in
                     * Move item details down a row to make room for the title
                     * Move the title directly above the details
                     * Adjust margins and padding for details
                     * Use a different font for title and subtitle
                     * Adjust margins below subtitle
                 -->
                <VisualState x:Name="Snapped_Detail">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedBackButtonStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedPageHeaderTextStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="primaryColumn" Storyboard.TargetProperty="Width">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="(Grid.Row)">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="(Grid.RowSpan)">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="titlePanel" Storyboard.TargetProperty="(Grid.Column)">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
                        </ObjectAnimationUsingKeyFrames>
                        <!--<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetailTitlePanel" Storyboard.TargetProperty="(Grid.Row)">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
                        </ObjectAnimationUsingKeyFrames>-->
                        <!--<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetailTitlePanel" Storyboard.TargetProperty="(Grid.Column)">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
                        </ObjectAnimationUsingKeyFrames>-->
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="Padding">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="20,0,20,0"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetailGrid" Storyboard.TargetProperty="Margin">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="0,0,0,60"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemTitle" Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TitleTextStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemTitle" Storyboard.TargetProperty="Margin">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
                        </ObjectAnimationUsingKeyFrames>
                        <!--<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemSubtitle" Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource CaptionTextStyle}"/>
                        </ObjectAnimationUsingKeyFrames>-->
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>
</common:LayoutAwarePage>

SplitPage.xaml.cs/vb

using System;
using System.Collections.Generic;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;

// The Split Page item template is documented at https://go.microsoft.com/fwlink/p/?LinkID=234234

namespace WindowsBlogReader
{
    /// <summary>
    /// A page that displays a group title, a list of items within the group, and details for
    /// the currently selected item.
    /// </summary>
    public sealed partial class SplitPage : WindowsBlogReader.Common.LayoutAwarePage
    {
        public SplitPage()
        {
            this.InitializeComponent();
        }

        private void ViewDetail_Click(object sender, RoutedEventArgs e)
        {
            FeedItem selectedItem = this.itemListView.SelectedItem as FeedItem;
            if (selectedItem != null && this.Frame != null)
            {
                string itemTitle = selectedItem.Title;
                this.Frame.Navigate(typeof(DetailPage), itemTitle);
            }
        }

        #region Page state management

        /// <summary>
        /// Populates the page with content passed during navigation.  Any saved state is also
        /// provided when recreating a page from a prior session.
        /// </summary>
        /// <param name="navigationParameter">The parameter value passed to
        /// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested.
        /// </param>
        /// <param name="pageState">A dictionary of state preserved by this page during an earlier
        /// session.  This will be null the first time a page is visited.</param>
        protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
        {
            // Run the PopInThemeAnimation 
            Windows.UI.Xaml.Media.Animation.Storyboard sb =
                this.FindName("PopInStoryboard") as Windows.UI.Xaml.Media.Animation.Storyboard;
            if (sb != null) sb.Begin();

            // TODO: Assign a bindable group to this.DefaultViewModel["Group"]
            // TODO: Assign a collection of bindable items to this.DefaultViewModel["Items"]
            string feedTitle = (string)navigationParameter;
            FeedData feedData = FeedDataSource.GetFeed(feedTitle);
            if (feedData != null)
            {
                this.DefaultViewModel["Feed"] = feedData;
                this.DefaultViewModel["Items"] = feedData.Items;
            }

            if (pageState == null)
            {
                // When this is a new page, select the first item automatically unless logical page
                // navigation is being used (see the logical page navigation #region below.)
                if (!this.UsingLogicalPageNavigation() && this.itemsViewSource.View != null)
                {
                    this.itemsViewSource.View.MoveCurrentToFirst();
                }
                else
                {
                    this.itemsViewSource.View.MoveCurrentToPosition(-1);
                }
            }
            else
            {
                // Restore the previously saved state associated with this page
                if (pageState.ContainsKey("SelectedItem") && this.itemsViewSource.View != null)
                {
                    // TODO: Invoke this.itemsViewSource.View.MoveCurrentTo() with the selected
                    //       item as specified by the value of pageState["SelectedItem"]
                    string itemTitle = (string)pageState["SelectedItem"];
                    FeedItem selectedItem = FeedDataSource.GetItem(itemTitle);
                    this.itemsViewSource.View.MoveCurrentTo(selectedItem);
                }
            }
        }

        /// <summary>
        /// Preserves state associated with this page in case the application is suspended or the
        /// page is discarded from the navigation cache.  Values must conform to the serialization
        /// requirements of <see cref="SuspensionManager.SessionState"/>.
        /// </summary>
        /// <param name="pageState">An empty dictionary to be populated with serializable state.</param>
        protected override void SaveState(Dictionary<String, Object> pageState)
        {
            if (this.itemsViewSource.View != null)
            {
                var selectedItem = this.itemsViewSource.View.CurrentItem;
                // TODO: Derive a serializable navigation parameter and assign it to
                //       pageState["SelectedItem"]
                if (selectedItem != null)
                {
                    string itemTitle = ((FeedItem)selectedItem).Title;
                    pageState["SelectedItem"] = itemTitle;
                }
            }
        }

        #endregion

        #region Logical page navigation

        // Visual state management typically reflects the four application view states directly
        // (full screen landscape and portrait plus snapped and filled views.)  The split page is
        // designed so that the snapped and portrait view states each have two distinct sub-states:
        // either the item list or the details are displayed, but not both at the same time.
        //
        // This is all implemented with a single physical page that can represent two logical
        // pages.  The code below achieves this goal without making the user aware of the
        // distinction.

        /// <summary>
        /// Invoked to determine whether the page should act as one logical page or two.
        /// </summary>
        /// <param name="viewState">The view state for which the question is being posed, or null
        /// for the current view state.  This parameter is optional with null as the default
        /// value.</param>
        /// <returns>True when the view state in question is portrait or snapped, false
        /// otherwise.</returns>
        private bool UsingLogicalPageNavigation(ApplicationViewState? viewState = null)
        {
            if (viewState == null) viewState = ApplicationView.Value;
            return viewState == ApplicationViewState.FullScreenPortrait ||
                viewState == ApplicationViewState.Snapped;
        }

        /// <summary>
        /// Invoked when an item within the list is selected.
        /// </summary>
        /// <param name="sender">The GridView (or ListView when the application is Snapped)
        /// displaying the selected item.</param>
        /// <param name="e">Event data that describes how the selection was changed.</param>
        void ItemListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // Invalidate the view state when logical page navigation is in effect, as a change
            // in selection may cause a corresponding change in the current logical page.  When
            // an item is selected this has the effect of changing from displaying the item list
            // to showing the selected item's details.  When the selection is cleared this has the
            // opposite effect.
            if (this.UsingLogicalPageNavigation()) this.InvalidateVisualState();

            // Add this code to populate the web view
            //  with the content of the selected blog post.
            Selector list = sender as Selector;
            FeedItem selectedItem = list.SelectedItem as FeedItem;
            if (selectedItem != null)
            {
                this.contentView.NavigateToString(selectedItem.Content);
            }
            else
            {
                this.contentView.NavigateToString("");
            }      
        }

        /// <summary>
        /// Invoked when the page's back button is pressed.
        /// </summary>
        /// <param name="sender">The back button instance.</param>
        /// <param name="e">Event data that describes how the back button was clicked.</param>
        protected override void GoBack(object sender, RoutedEventArgs e)
        {
            if (this.UsingLogicalPageNavigation() && itemListView.SelectedItem != null)
            {
                // When logical page navigation is in effect and there's a selected item that
                // item's details are currently displayed.  Clearing the selection will return to
                // the item list.  From the user's point of view this is a logical backward
                // navigation.
                this.itemListView.SelectedItem = null;
            }
            else
            {
                // When logical page navigation is not in effect, or when there is no selected
                // item, use the default back button behavior.
                base.GoBack(sender, e);
            }
        }

        /// <summary>
        /// Invoked to determine the name of the visual state that corresponds to an application
        /// view state.
        /// </summary>
        /// <param name="viewState">The view state for which the question is being posed.</param>
        /// <returns>The name of the desired visual state.  This is the same as the name of the
        /// view state except when there is a selected item in portrait and snapped views where
        /// this additional logical page is represented by adding a suffix of _Detail.</returns>
        protected override string DetermineVisualState(ApplicationViewState viewState)
        {
            // Update the back button's enabled state when the view state changes
            var logicalPageBack = this.UsingLogicalPageNavigation(viewState) && this.itemListView.SelectedItem != null;
            var physicalPageBack = this.Frame != null && this.Frame.CanGoBack;
            this.DefaultViewModel["CanGoBack"] = logicalPageBack || physicalPageBack;

            // Determine visual states for landscape layouts based not on the view state, but
            // on the width of the window.  This page has one layout that is appropriate for
            // 1366 virtual pixels or wider, and another for narrower displays or when a snapped
            // application reduces the horizontal space available to less than 1366.
            if (viewState == ApplicationViewState.Filled ||
                viewState == ApplicationViewState.FullScreenLandscape)
            {
                var windowWidth = Window.Current.Bounds.Width;
                if (windowWidth >= 1366) return "FullScreenLandscapeOrWide";
                return "FilledOrNarrow";
            }

            // When in portrait or snapped start with the default visual state name, then add a
            // suffix when viewing details instead of the list
            var defaultStateName = base.DetermineVisualState(viewState);
            return logicalPageBack ? defaultStateName + "_Detail" : defaultStateName;
        }

        #endregion

        private void contentView_NavigationCompleted(object sender, WebViewNavigationCompletedEventArgs e)
        {
            if (!e.IsSuccess)
            {
                string errorString = "<p>Page could not be loaded.</p><p>Error is: " + e.WebErrorStatus.ToString() + "</p>";
                this.contentView.NavigateToString(errorString);
             }
        }
    }
}
' The Split Page item template is documented at https://go.microsoft.com/fwlink/p/?LinkID=234234

''' <summary>
''' A page that displays a group title, a list of items within the group, and details for
''' the currently selected item.
''' </summary>
Public NotInheritable Class SplitPage
    Inherits Common.LayoutAwarePage

    Private Sub ViewDetail_Click(sender As Object, e As RoutedEventArgs)
        Dim selectedItem = DirectCast(Me.itemListView.SelectedItem, FeedItem)
        If selectedItem IsNot Nothing AndAlso Me.Frame IsNot Nothing Then
            Dim itemTitle = selectedItem.Title
            Me.Frame.Navigate(GetType(DetailPage), itemTitle)
        End If
    End Sub

    #Region "Page state management"

    ''' <summary>
    ''' Populates the page with content passed during navigation.  Any saved state is also
    ''' provided when recreating a page from a prior session.
    ''' </summary>
    ''' <param name="navigationParameter">The parameter value passed to <see cref="Frame.Navigate"/>
    ''' when this page was initially requested.
    ''' </param>
    ''' <param name="pageState">A dictionary of state preserved by this page during an earlier
    ''' session.  This will be null the first time a page is visited.</param>
    Protected Overrides Sub LoadState(navigationParameter As Object, pageState As Dictionary(Of String, Object))
        ' Run the PopInThemeAnimation 
        Dim sb As Windows.UI.Xaml.Media.Animation.Storyboard = Me.FindName("PopInStoryboard")
        If sb IsNot Nothing Then
            sb.Begin()
        End If

        ' TODO: Assign a bindable group to Me.DefaultViewModel("Group")
        ' TODO: Assign a collection of bindable items to Me.DefaultViewModel("Items")
        Dim feedTitle = DirectCast(navigationParameter, String)

        Dim feedData = FeedDataSource.GetFeed(feedTitle)
        If feedData IsNot Nothing Then
            Me.DefaultViewModel("Feed") = feedData
            Me.DefaultViewModel("Items") = feedData.Items
        End If


        If pageState Is Nothing Then

            ' When this is a new page, select the first item automatically unless logical page
            ' navigation is being used (see the logical page navigation #region below.)
            If Not Me.UsingLogicalPageNavigation() AndAlso Me.itemsViewSource.View IsNot Nothing Then
                Me.itemsViewSource.View.MoveCurrentToFirst()
            Else
                Me.itemsViewSource.View.MoveCurrentToPosition(-1)
            End If
        Else

            ' Restore the previously saved state associated with this page
            If pageState.ContainsKey("SelectedItem") AndAlso Me.itemsViewSource.View IsNot Nothing Then
                ' TODO: Invoke Me.itemsViewSource.View.MoveCurrentTo() with the selected
                '       item as specified by the value of pageState("SelectedItem")
                Dim itemTitle = DirectCast(pageState("SelectedItem"), String)
                Dim selectedItem = FeedDataSource.GetItem(itemTitle)
                Me.itemsViewSource.View.MoveCurrentTo(selectedItem)
            End If
        End If
    End Sub

    ''' <summary>
    ''' Preserves state associated with this page in case the application is suspended or the
    ''' page is discarded from the navigation cache.  Values must conform to the serialization
    ''' requirements of <see cref="Common.SuspensionManager.SessionState"/>.
    ''' </summary>
    ''' <param name="pageState">An empty dictionary to be populated with serializable state.</param>
    Protected Overrides Sub SaveState(pageState As Dictionary(Of String, Object))
        If Me.itemsViewSource.View IsNot Nothing Then
            Dim selectedItem As Object = Me.itemsViewSource.View.CurrentItem
            ' TODO: Derive a serializable navigation parameter and assign it to
            '       pageState("SelectedItem")
            If selectedItem IsNot Nothing Then
                Dim itemTitle = (DirectCast(selectedItem, FeedItem)).Title
                pageState("SelectedItem") = itemTitle
            End If

        End If
    End Sub

    #End Region

    #Region "Logical page navigation"

    ' Visual state management typically reflects the four application view states directly
    ' (full screen landscape and portrait plus snapped and filled views.)  The split page is
    ' designed so that the snapped and portrait view states each have two distinct sub-states:
    ' either the item list or the details are displayed, but not both at the same time.
    '
    ' This is all implemented with a single physical page that can represent two logical
    ' pages.  The code below achieves this goal without making the user aware of the
    ' distinction.

    ''' <summary>
    ''' Invoked to determine whether the page should act as one logical page or two.
    ''' </summary>
    ''' <param name="viewState">The view state for which the question is being posed, or null
    ''' for the current view state.  This parameter is optional with null as the default
    ''' value.</param>
    ''' <returns>True when the view state in question is portrait or snapped, false
    ''' otherwise.</returns>
    Private Function UsingLogicalPageNavigation(Optional viewState As ApplicationViewState? = Nothing) As Boolean
        If Not viewState.HasValue Then viewState = ApplicationView.Value
        Return viewState.Value = ApplicationViewState.FullScreenPortrait OrElse
            viewState.Value = ApplicationViewState.Snapped
    End Function

    ''' <summary>
    ''' Invoked when an item within the list is selected.
    ''' </summary>
    ''' <param name="sender">The GridView (or ListView when the application is Snapped)
    ''' displaying the selected item.</param>
    ''' <param name="e">Event data that describes how the selection was changed.</param>
    Private Sub ItemListView_SelectionChanged(sender As Object, e As SelectionChangedEventArgs)

        ' Invalidate the view state when logical page navigation is in effect, as a change in
        ' selection may cause a corresponding change in the current logical page.  When an item
        ' is selected this has the effect of changing from displaying the item list to showing
        ' the selected item's details.  When the selection is cleared this has the opposite effect.
        If Me.UsingLogicalPageNavigation Then Me.InvalidateVisualState()

        ' Add this code to populate the web view
        ' with the content of the selected blog post.
        Dim list = DirectCast(sender, Selector)
        Dim selectedItem = DirectCast(list.SelectedItem, FeedItem)
        If selectedItem IsNot Nothing Then
            Me.contentView.NavigateToString(selectedItem.Content)
        Else
            Me.contentView.NavigateToString("")
        End If

    End Sub

    ''' <summary>
    ''' Invoked when the page's back button is pressed.
    ''' </summary>
    ''' <param name="sender">The back button instance.</param>
    ''' <param name="e">Event data that describes how the back button was clicked.</param>
    Protected Overrides Sub GoBack(sender As Object, e As RoutedEventArgs)
        If Me.UsingLogicalPageNavigation() AndAlso Me.itemListView.SelectedItem IsNot Nothing Then

            ' When logical page navigation is in effect and there's a selected item that item's
            ' details are currently displayed.  Clearing the selection will return to the item
            ' list.  From the user's point of view this is a logical backward navigation.
            Me.itemListView.SelectedItem = Nothing
        Else

            ' When logical page navigation is not in effect, or when there is no selected item,
            ' use the default back button behavior.
            MyBase.GoBack(sender, e)
        End If
    End Sub

    ''' <summary>
    ''' Invoked to determine the name of the visual state that corresponds to an application
    ''' view state.
    ''' </summary>
    ''' <param name="viewState">The view state for which the question is being posed.</param>
    ''' <returns>The name of the desired visual state.  This is the same as the name of the
    ''' view state except when there is a selected item in portrait and snapped views where
    ''' this additional logical page is represented by adding a suffix of _Detail.</returns>
    Protected Overrides Function DetermineVisualState(viewState As ApplicationViewState) As String

        ' Update the back button's enabled state when the view state changes
        Dim logicalPageBack As Boolean = Me.UsingLogicalPageNavigation(viewState) AndAlso Me.itemListView.SelectedItem IsNot Nothing
        Dim physicalPageBack As Boolean = Me.Frame IsNot Nothing AndAlso Me.Frame.CanGoBack
        Me.DefaultViewModel("CanGoBack") = logicalPageBack OrElse physicalPageBack

        ' Determine visual states for landscape layouts based not on the view state, but
        ' on the width of the window.  This page has one layout that is appropriate for
        ' 1366 virtual pixels or wider, and another for narrower displays or when a snapped
        ' application reduces the horizontal space available to less than 1366.
        If viewState = ApplicationViewState.Filled OrElse
            viewState = ApplicationViewState.FullScreenLandscape Then

            Dim windowWidth As Double = Window.Current.Bounds.Width
            If windowWidth >= 1366 Then Return "FullScreenLandscapeOrWide"
            Return "FilledOrNarrow"
        End If

        ' When in portrait or snapped start with the default visual state name, then add a
        ' suffix when viewing details instead of the list
        Dim defaultStateName As String = MyBase.DetermineVisualState(viewState)
        If logicalPageBack Then Return defaultStateName + "_Detail"
        Return defaultStateName
    End Function

    #End Region

    Private Sub ContentView_NavigationFailed(sender As Object, e As WebViewNavigationFailedEventArgs) _
        Handles contentView.NavigationFailed
        Dim errorString = "<p>Page could not be loaded.</p><p>Error is: " & e.WebErrorStatus.ToString() & "</p>"
        Me.contentView.NavigateToString(errorString)
    End Sub
End Class

DetailPage.xaml

<common:LayoutAwarePage
    x:Name="pageRoot"
    x:Class="WindowsBlogReader.DetailPage"
    DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WindowsBlogReader"
    xmlns:common="using:WindowsBlogReader.Common"
    xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Page.Resources>

        <!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
        <x:String x:Key="AppName">My Application</x:String>

        <Storyboard x:Name="PopInStoryboard">
            <PopInThemeAnimation  Storyboard.TargetName="contentViewBorder" 
                              FromHorizontalOffset="400"/>
        </Storyboard>
    </Page.Resources>

    <!--
        This grid acts as a root panel for the page that defines two rows:
        * Row 0 contains the back button and page title
        * Row 1 contains the rest of the page layout
    -->
    <Grid Style="{StaticResource WindowsBlogLayoutRootStyle}">
        <Grid.RowDefinitions>
            <RowDefinition Height="140"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!-- Back button and page title -->
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Button x:Name="backButton" Click="GoBack" 
                    IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" 
                    Style="{StaticResource BackButtonStyle}"/>
            <TextBlock x:Name="pageTitle" Grid.Column="1" Text="{Binding Title}" 
                       Style="{StaticResource PageHeaderTextStyle}"/>
        </Grid>


        <Border x:Name="contentViewBorder" BorderBrush="Gray" BorderThickness="2" 
                Grid.Row="1" Margin="120,15,20,20">
            <WebView x:Name="contentView" 
                     NavigationCompleted="contentView_NavigationCompleted"/>
        </Border>
        
        <VisualStateManager.VisualStateGroups>

            <!-- Visual states reflect the application's view state -->
            <VisualStateGroup x:Name="ApplicationViewStates">
                <VisualState x:Name="FullScreenLandscape"/>
                <VisualState x:Name="Filled"/>

                <!-- The entire page respects the narrower 100-pixel margin convention for portrait -->
                <VisualState x:Name="FullScreenPortrait">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" 
                                                       Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" 
                                                    Value="{StaticResource PortraitBackButtonStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>

                <!-- The back button and title have different styles when snapped -->
                <VisualState x:Name="Snapped">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" 
                                                       Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" 
                                                    Value="{StaticResource SnappedBackButtonStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" 
                                                       Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" 
                                                    Value="{StaticResource SnappedPageHeaderTextStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                        
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="contentViewBorder" 
                                                       Storyboard.TargetProperty="Margin">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="20,5,20,20"/>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>
</common:LayoutAwarePage>

DetailPage.xaml.cs/vb

using System;
using System.Collections.Generic;
using Windows.UI.Xaml.Controls;

// The Basic Page item template is documented at https://go.microsoft.com/fwlink/p/?LinkID=234237

namespace WindowsBlogReader
{
    /// <summary>
    /// A basic page that provides characteristics common to most applications.
    /// </summary>
    public sealed partial class DetailPage : WindowsBlogReader.Common.LayoutAwarePage
    {
        public DetailPage()
        {
            this.InitializeComponent();
        }

        /// <summary>
        /// Populates the page with content passed during navigation.  Any saved state is also
        /// provided when recreating a page from a prior session.
        /// </summary>
        /// <param name="navigationParameter">The parameter value passed to
        /// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested.
        /// </param>
        /// <param name="pageState">A dictionary of state preserved by this page during an earlier
        /// session.  This will be null the first time a page is visited.</param>
        protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
        {
            // Run the PopInThemeAnimation 
            Windows.UI.Xaml.Media.Animation.Storyboard sb =
                this.FindName("PopInStoryboard") as Windows.UI.Xaml.Media.Animation.Storyboard;
            if (sb != null) sb.Begin();

            // Add this code to navigate the web view to the selected blog post.
            string itemTitle = (string)navigationParameter;
            FeedItem feedItem = FeedDataSource.GetItem(itemTitle);
            if (feedItem != null)
            {
                this.contentView.Navigate(feedItem.Link);
                this.DataContext = feedItem;
            }
        }

        /// <summary>
        /// Preserves state associated with this page in case the application is suspended or the
        /// page is discarded from the navigation cache.  Values must conform to the serialization
        /// requirements of <see cref="SuspensionManager.SessionState"/>.
        /// </summary>
        /// <param name="pageState">An empty dictionary to be populated with serializable state.</param>
        protected override void SaveState(Dictionary<String, Object> pageState)
        {
        }

        private void contentView_NavigationCompleted(object sender, WebViewNavigationCompletedEventArgs e)
        {
            if (!e.IsSuccess)
            {
                string errorString = "<p>Page could not be loaded.</p><p>Error is: " + e.WebErrorStatus.ToString() + "</p>";
                this.contentView.NavigateToString(errorString);
            }
        }
    }
}
' The Basic Page item template is documented at https://go.microsoft.com/fwlink/p/?LinkID=234237

''' <summary>
''' A basic page that provides characteristics common to most applications.
''' </summary>
Public NotInheritable Class DetailPage
    Inherits Common.LayoutAwarePage

    ''' <summary>
    ''' Populates the page with content passed during navigation.  Any saved state is also
    ''' provided when recreating a page from a prior session.
    ''' </summary>
    ''' <param name="navigationParameter">The parameter value passed to
    ''' <see cref="Frame.Navigate"/> when this page was initially requested.
    ''' </param>
    ''' <param name="pageState">A dictionary of state preserved by this page during an earlier
    ''' session.  This will be null the first time a page is visited.</param>
    Protected Overrides Sub LoadState(navigationParameter As Object, pageState As Dictionary(Of String, Object))
        ' Run the PopInThemeAnimation 
        Dim sb As Windows.UI.Xaml.Media.Animation.Storyboard = Me.FindName("PopInStoryboard")
        If sb IsNot Nothing Then
            sb.Begin()
        End If

        ' Add this code to navigate the web view to the selected blog post.
        Dim itemTitle = DirectCast(navigationParameter, String)
        Dim feedItem = FeedDataSource.GetItem(itemTitle)
        If feedItem IsNot Nothing Then
            Me.contentView.Navigate(feedItem.Link)
            Me.DataContext = feedItem
        End If
    End Sub

    ''' <summary>
    ''' Preserves state associated with this page in case the application is suspended or the
    ''' page is discarded from the navigation cache.  Values must conform to the serialization
    ''' requirements of <see cref="Common.SuspensionManager.SessionState"/>.
    ''' </summary>
    ''' <param name="pageState">An empty dictionary to be populated with serializable state.</param>
    Protected Overrides Sub SaveState(pageState As Dictionary(Of String, Object))

    End Sub

    Private Sub contentView_NavigationFailed(sender As Object, e As WebViewNavigationFailedEventArgs)
        Dim errorString = "<p>Page could not be loaded.</p><p>Error is: " & e.WebErrorStatus.ToString() & "</p>"
        Me.contentView.NavigateToString(errorString)
    End Sub

End Class

FeedData.cs/vb

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using Windows.Web.Syndication;

namespace WindowsBlogReader
{
    // FeedData
    // Holds info for a single blog feed, including a list of blog posts (FeedItem).
    public class FeedData
    {
        public string Title { get; set; }
        public string Description { get; set; }
        public DateTime PubDate { get; set; }

        private List<FeedItem> _Items = new List<FeedItem>();
        public List<FeedItem> Items
        {
            get
            {
                return this._Items;
            }
        }
    }

    // FeedItem
    // Holds info for a single blog post.
    public class FeedItem
    {
        public string Title { get; set; }
        public string Author { get; set; }
        public string Content { get; set; }
        public DateTime PubDate { get; set; }
        public Uri Link { get; set; }
    }

    // FeedDataSource
    // Holds a collection of blog feeds (FeedData), and contains methods needed to
    // retreive the feeds.
    public class FeedDataSource
    {
        private ObservableCollection<FeedData> _Feeds = new ObservableCollection<FeedData>();
        public ObservableCollection<FeedData> Feeds
        {
            get
            {
                return this._Feeds;
            }
        }

        public async Task GetFeedsAsync()
        {
            Task<FeedData> feed1 =
                GetFeedAsync("https://windowsteamblog.com/windows/b/developers/atom.aspx");
            Task<FeedData> feed2 =
                GetFeedAsync("https://windowsteamblog.com/windows/b/windowsexperience/atom.aspx");
            Task<FeedData> feed3 =
                GetFeedAsync("https://windowsteamblog.com/windows/b/extremewindows/atom.aspx");
            Task<FeedData> feed4 =
                GetFeedAsync("https://windowsteamblog.com/windows/b/business/atom.aspx");
            Task<FeedData> feed5 =
                GetFeedAsync("https://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx");
            Task<FeedData> feed6 =
                GetFeedAsync("https://windowsteamblog.com/windows/b/windowssecurity/atom.aspx");
            Task<FeedData> feed7 =
                GetFeedAsync("https://windowsteamblog.com/windows/b/springboard/atom.aspx");
            Task<FeedData> feed8 =
                GetFeedAsync("https://windowsteamblog.com/windows/b/windowshomeserver/atom.aspx");
            // There is no Atom feed for this blog, so use the RSS feed.
            Task<FeedData> feed9 =
                GetFeedAsync("https://windowsteamblog.com/windows_live/b/windowslive/rss.aspx");
            Task<FeedData> feed10 =
                GetFeedAsync("https://windowsteamblog.com/windows_live/b/developer/atom.aspx");
            Task<FeedData> feed11 =
                GetFeedAsync("https://windowsteamblog.com/ie/b/ie/atom.aspx");
            Task<FeedData> feed12 =
                GetFeedAsync("https://windowsteamblog.com/windows_phone/b/wpdev/atom.aspx");
            Task<FeedData> feed13 =
                GetFeedAsync("https://windowsteamblog.com/windows_phone/b/wmdev/atom.aspx");
            Task<FeedData> feed14 =
                GetFeedAsync("https://windowsteamblog.com/windows_phone/b/windowsphone/atom.aspx");

            this.Feeds.Add(await feed1);
            this.Feeds.Add(await feed2);
            this.Feeds.Add(await feed3);
            this.Feeds.Add(await feed4);
            this.Feeds.Add(await feed5);
            this.Feeds.Add(await feed6);
            this.Feeds.Add(await feed7);
            this.Feeds.Add(await feed8);
            this.Feeds.Add(await feed9);
            this.Feeds.Add(await feed10);
            this.Feeds.Add(await feed11);
            this.Feeds.Add(await feed12);
            this.Feeds.Add(await feed13);
            this.Feeds.Add(await feed14);
        }

        private async Task<FeedData> GetFeedAsync(string feedUriString)
        {
            Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();
            Uri feedUri = new Uri(feedUriString);

            try
            {
                SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri);

                // This code is executed after RetrieveFeedAsync returns the SyndicationFeed.
                // Process the feed and copy the data you want into the FeedData and FeedItem classes.
                FeedData feedData = new FeedData();

                if (feed.Title != null && feed.Title.Text != null)
                {
                    feedData.Title = feed.Title.Text;
                }
                if (feed.Subtitle != null && feed.Subtitle.Text != null)
                {
                    feedData.Description = feed.Subtitle.Text;
                }
                if (feed.Items != null && feed.Items.Count > 0)
                {
                    // Use the date of the latest post as the last updated date.
                    feedData.PubDate = feed.Items[0].PublishedDate.DateTime;

                    foreach (SyndicationItem item in feed.Items)
                    {
                        FeedItem feedItem = new FeedItem();
                        if (item.Title != null && item.Title.Text != null)
                        {
                            feedItem.Title = item.Title.Text;
                        }
                        if (item.PublishedDate != null)
                        {
                            feedItem.PubDate = item.PublishedDate.DateTime;
                        }
                        if (item.Authors != null && item.Authors.Count > 0)
                        {
                            feedItem.Author = item.Authors[0].Name.ToString();
                        }
                        // Handle the differences between RSS and Atom feeds.
                        if (feed.SourceFormat == SyndicationFormat.Atom10)
                        {
                            if (item.Content != null && item.Content.Text != null)
                            {
                                feedItem.Content = item.Content.Text;
                            }
                            if (item.Id != null)
                            {
                                feedItem.Link = new Uri("https://windowsteamblog.com" + item.Id);
                            }
                        }
                        else if (feed.SourceFormat == SyndicationFormat.Rss20)
                        {
                            if (item.Summary != null && item.Summary.Text != null)
                            {
                                feedItem.Content = item.Summary.Text;
                            }
                            if (item.Links != null && item.Links.Count > 0)
                            {
                                feedItem.Link = item.Links[0].Uri;
                            }
                        }
                        feedData.Items.Add(feedItem);
                    }    
                }
                return feedData;
            }
            catch (Exception)
            {
                return null;
            }
        }

        // Returns the feed that has the specified title.
        public static FeedData GetFeed(string title)
        {
            // Simple linear search is acceptable for small data sets
            var _feedDataSource = App.Current.Resources["feedDataSource"] as FeedDataSource;

            var matches = _feedDataSource.Feeds.Where((feed) => feed.Title.Equals(title));
            if (matches.Count() == 1) return matches.First();
            return null;
        }

        // Returns the post that has the specified title.
        public static FeedItem GetItem(string uniqueId)
        {
            // Simple linear search is acceptable for small data sets
            var _feedDataSource = App.Current.Resources["feedDataSource"] as FeedDataSource;
            var _feeds = _feedDataSource.Feeds;

            var matches = _feedDataSource.Feeds.SelectMany(group => group.Items).Where((item) => item.Title.Equals(uniqueId));
            if (matches.Count() == 1) return matches.First();
            return null;
        }
    }
}
Imports Windows.Web.Syndication

' FeedData
' Holds info for a single blog feed, including a list of blog posts (FeedItem).
Public Class FeedData
    Public Property Title() As String = String.Empty
    Public Property Description() As String = String.Empty
    Public Property PubDate() As DateTime

    Private _Items As New List(Of FeedItem)()
    Public ReadOnly Property Items() As List(Of FeedItem)
        Get
            Return Me._Items
        End Get
    End Property
End Class

' FeedItem
' Holds info for a single blog post.
Public Class FeedItem
    Public Property Title() As String = String.Empty
    Public Property Author() As String = String.Empty
    Public Property Content() As String = String.Empty
    Public Property PubDate() As DateTime
    Public Property Link() As Uri
End Class

' FeedDataSource
' Holds a collection of blog feeds (FeedData), and contains methods needed to
' retreive the feeds.
Public Class FeedDataSource
    Private _Feeds As New ObservableCollection(Of FeedData)()
    Public ReadOnly Property Feeds() As ObservableCollection(Of FeedData)
        Get
            Return Me._Feeds
        End Get
    End Property

    Public Async Function GetFeedsAsync() As Task
        Dim feed1 As Task(Of FeedData) =
            GetFeedAsync("https://windowsteamblog.com/windows/b/developers/atom.aspx")
        Dim feed2 As Task(Of FeedData) =
            GetFeedAsync("https://windowsteamblog.com/windows/b/windowsexperience/atom.aspx")
        Dim feed3 As Task(Of FeedData) =
            GetFeedAsync("https://windowsteamblog.com/windows/b/extremewindows/atom.aspx")
        Dim feed4 As Task(Of FeedData) =
            GetFeedAsync("https://windowsteamblog.com/windows/b/business/atom.aspx")
        Dim feed5 As Task(Of FeedData) =
            GetFeedAsync("https://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx")
        Dim feed6 As Task(Of FeedData) =
            GetFeedAsync("https://windowsteamblog.com/windows/b/windowssecurity/atom.aspx")
        Dim feed7 As Task(Of FeedData) =
            GetFeedAsync("https://windowsteamblog.com/windows/b/springboard/atom.aspx")
        Dim feed8 As Task(Of FeedData) =
            GetFeedAsync("https://windowsteamblog.com/windows/b/windowshomeserver/atom.aspx")
        ' There is no Atom feed for this blog, so use the RSS feed.
        Dim feed9 As Task(Of FeedData) =
            GetFeedAsync("https://windowsteamblog.com/windows_live/b/windowslive/rss.aspx")
        Dim feed10 As Task(Of FeedData) =
            GetFeedAsync("https://windowsteamblog.com/windows_live/b/developer/atom.aspx")
        Dim feed11 As Task(Of FeedData) =
            GetFeedAsync("https://windowsteamblog.com/ie/b/ie/atom.aspx")
        Dim feed12 As Task(Of FeedData) =
            GetFeedAsync("https://windowsteamblog.com/windows_phone/b/wpdev/atom.aspx")
        Dim feed13 As Task(Of FeedData) =
            GetFeedAsync("https://windowsteamblog.com/windows_phone/b/wmdev/atom.aspx")
        Dim feed14 As Task(Of FeedData) =
            GetFeedAsync("https://windowsteamblog.com/windows_phone/b/windowsphone/atom.aspx")

        Me.Feeds.Add(Await feed1)
        Me.Feeds.Add(Await feed2)
        Me.Feeds.Add(Await feed3)
        Me.Feeds.Add(Await feed4)
        Me.Feeds.Add(Await feed5)
        Me.Feeds.Add(Await feed6)
        Me.Feeds.Add(Await feed7)
        Me.Feeds.Add(Await feed8)
        Me.Feeds.Add(Await feed9)
        Me.Feeds.Add(Await feed10)
        Me.Feeds.Add(Await feed11)
        Me.Feeds.Add(Await feed12)
        Me.Feeds.Add(Await feed13)
        Me.Feeds.Add(Await feed14)
    End Function

    Private Async Function GetFeedAsync(feedUriString As String) As Task(Of FeedData)
        Dim Client As New SyndicationClient
        Dim FeedUri As New Uri(feedUriString)

        Try
            Dim Feed As SyndicationFeed = Await Client.RetrieveFeedAsync(FeedUri)

            ' This code is executed after RetrieveFeedAsync returns the SyndicationFeed.
            ' Process the feed and copy the data you want into the FeedData and FeedItem classes.
            Dim FeedData As New FeedData

            If Feed.Title IsNot Nothing AndAlso Feed.Title.Text IsNot Nothing Then
                FeedData.Title = Feed.Title.Text
            End If
            If Feed.Subtitle IsNot Nothing AndAlso Feed.Subtitle.Text IsNot Nothing Then
                FeedData.Description = Feed.Subtitle.Text
            End If
            If Feed.Items IsNot Nothing AndAlso Feed.Items.Count > 0 Then
                ' Use the date of the latest post as the last updated date.
                FeedData.PubDate = Feed.Items(0).PublishedDate.DateTime
                For Each Item As SyndicationItem In Feed.Items
                    Dim FeedItem As New FeedItem
                    If Item.Title IsNot Nothing AndAlso Item.Title.Text IsNot Nothing Then
                        FeedItem.Title = Item.Title.Text
                    End If
                    FeedItem.PubDate = Item.PublishedDate.DateTime
                    If Item.Authors IsNot Nothing AndAlso Item.Authors.Count > 0 Then
                        FeedItem.Author = Item.Authors(0).Name.ToString()
                    End If
                    ' Handle the differences between RSS and Atom feeds.
                    If Feed.SourceFormat = SyndicationFormat.Atom10 Then
                        If Item.Content IsNot Nothing AndAlso Item.Content.Text IsNot Nothing Then
                            FeedItem.Content = Item.Content.Text
                        End If
                        If Item.Id IsNot Nothing Then
                            FeedItem.Link = New Uri("https://windowsteamblog.com" + Item.Id)
                        End If
                    ElseIf Feed.SourceFormat = SyndicationFormat.Rss20 Then
                        If Item.Summary IsNot Nothing AndAlso Item.Summary.Text IsNot Nothing Then
                            FeedItem.Content = Item.Summary.Text
                        End If
                        If Item.Links IsNot Nothing AndAlso Item.Links.Count > 0 Then
                            FeedItem.Link = Item.Links(0).Uri
                        End If
                    End If
                    FeedData.Items.Add(FeedItem)
                Next
            End If
            Return FeedData

        Catch Ex As Exception
            Return Nothing
        End Try
    End Function

    Public Shared Function GetFeed(title As String) As FeedData
        ' Simple linear search is acceptable for small data sets
        Dim _feedDataSource = DirectCast(App.Current.Resources("feedDataSource"), FeedDataSource)

        Dim matches = _feedDataSource.Feeds.Where(Function(feed) feed.Title.Equals(title))
        If matches.Count() = 1 Then
            Return matches.First()
        End If
        Return Nothing
    End Function

    Public Shared Function GetItem(uniqueId As String) As FeedItem
        ' Simple linear search is acceptable for small data sets
        Dim _feedDataSource = DirectCast(App.Current.Resources("feedDataSource"), FeedDataSource)
        Dim _feeds = _feedDataSource.Feeds

        Dim matches = _feedDataSource.Feeds.SelectMany(Function(group) group.Items).Where(Function(item) item.Title.Equals(uniqueId))

        If matches.Count() = 1 Then
            Return matches.First()
        End If
        Return Nothing
    End Function
End Class

DateConverter.cs/vb

using System;
using Windows.Globalization.DateTimeFormatting;

namespace WindowsBlogReader
{
    public class DateConverter : Windows.UI.Xaml.Data.IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string culture)
        {
            if (value == null)
                throw new ArgumentNullException("value", "Value cannot be null.");

            if (!typeof(DateTime).Equals(value.GetType()))
                throw new ArgumentException("Value must be of type DateTime.", "value");

            DateTime dt = (DateTime)value;

            if (parameter == null)
            {
                // Date "7/27/2011 9:30:59 AM" returns "7/27/2011"
                return DateTimeFormatter.ShortDate.Format(dt);
            }
            else if ((string)parameter == "day")
            {
                // Date "7/27/2011 9:30:59 AM" returns "27"
                DateTimeFormatter dateFormatter = new DateTimeFormatter("{day.integer(2)}");
                return dateFormatter.Format(dt);
            }
            else if ((string)parameter == "month")
            {
                // Date "7/27/2011 9:30:59 AM" returns "JUL"
                DateTimeFormatter dateFormatter = new DateTimeFormatter("{month.abbreviated(3)}");
                return dateFormatter.Format(dt).ToUpper();
            }
            else if ((string)parameter == "year")
            {
                // Date "7/27/2011 9:30:59 AM" returns "2011"
                DateTimeFormatter dateFormatter = new DateTimeFormatter("{year.full}");
                return dateFormatter.Format(dt);
            }
            else
            {
                // Requested format is unknown. Return in the original format.
                return dt.ToString();
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, string culture)
        {
            string strValue = value as string;
            DateTime resultDateTime;
            if (DateTime.TryParse(strValue, out resultDateTime))
            {
                return resultDateTime;
            }
            return Windows.UI.Xaml.DependencyProperty.UnsetValue;
        }
    }
}
Imports Windows.Globalization.DateTimeFormatting

Public Class DateConverter
    Implements IValueConverter

    Public Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As String) _
        As Object Implements IValueConverter.Convert
        If value Is Nothing Then
            Throw New ArgumentNullException("value", "Value cannot be null.")
        End If
        If Not GetType(DateTime).Equals(value.GetType()) Then
            Throw New ArgumentException("Value must be of type DateTime.", "value")
        End If

        Dim dt As DateTime = DirectCast(value, DateTime)

        If parameter Is Nothing Then
            ' Date "7/27/2011 9:30:59 AM" returns "7/27/2011"
            Return DateTimeFormatter.ShortDate.Format(dt)

        ElseIf DirectCast(parameter, String) = "day" Then
            ' Date "7/27/2011 9:30:59 AM" returns "27"
            Dim dateFormatter As DateTimeFormatter = New DateTimeFormatter("{day.integer(2)}")
            Return dateFormatter.Format(dt)

        ElseIf DirectCast(parameter, String) = "month" Then
            ' Date "7/27/2011 9:30:59 AM" returns "JUL"
            Dim dateFormatter As DateTimeFormatter = New DateTimeFormatter("{month.abbreviated(3)}")
            Return dateFormatter.Format(dt).ToUpper()

        ElseIf DirectCast(parameter, String) = "year" Then
            ' Date "7/27/2011 9:30:59 AM" returns "2011"
            Dim dateFormatter As DateTimeFormatter = New DateTimeFormatter("{year.full}")
            Return dateFormatter.Format(dt)

        Else
            ' Requested format is unknown. Return in the original format.
            Return dt.ToString()

        End If
    End Function

    Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As String) _
        As Object Implements Windows.UI.Xaml.Data.IValueConverter.ConvertBack
        Dim StrValue As String = DirectCast(value, String)
        Dim Result As Date
        If DateTime.TryParse(StrValue, Result) Then
            Return Result
        End If
        Return DependencyProperty.UnsetValue
    End Function
End Class