This topic provides the complete code sample used in the tutorial Part 5: Create a blog reader.
This topic contains these sections:
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 ()
App.xaml
<Application x:Class="WindowsBlogReader.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://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
' The Blank Application template is documented at http://go.microsoft.com/fwlink/?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="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:WindowsBlogReader" xmlns:common="using:WindowsBlogReader.Common" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://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
' The Items Page item template is documented at http://go.microsoft.com/fwlink/?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="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:WindowsBlogReader" xmlns:common="using:WindowsBlogReader.Common" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://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=""/> </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" NavigationFailed="ContentView_NavigationFailed" /> <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
' The Split Page item template is documented at http://go.microsoft.com/fwlink/?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="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:WindowsBlogReader" xmlns:common="using:WindowsBlogReader.Common" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://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" NavigationFailed="contentView_NavigationFailed"/> </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
' The Basic Page item template is documented at http://go.microsoft.com/fwlink/?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
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("http://blogs.windows.com/skydrive/b/skydrive/atom.aspx") Dim feed2 As Task(Of FeedData) = GetFeedAsync("http://blogs.windows.com/windows/b/windowsexperience/atom.aspx") Dim feed3 As Task(Of FeedData) = GetFeedAsync("http://blogs.windows.com/windows/b/extremewindows/atom.aspx") Dim feed4 As Task(Of FeedData) = GetFeedAsync("http://blogs.windows.com/windows/b/business/atom.aspx") Dim feed5 As Task(Of FeedData) = GetFeedAsync("http://blogs.windows.com/windows/b/bloggingwindows/atom.aspx") Dim feed6 As Task(Of FeedData) = GetFeedAsync("http://blogs.windows.com/windows/b/windowssecurity/atom.aspx") Dim feed7 As Task(Of FeedData) = GetFeedAsync("http://blogs.windows.com/windows/b/springboard/atom.aspx") Dim feed8 As Task(Of FeedData) = GetFeedAsync("http://blogs.windows.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("http://blogs.windows.com/windows_live/b/windowslive/rss.aspx") Dim feed10 As Task(Of FeedData) = GetFeedAsync("http://blogs.windows.com/windows_live/b/developer/atom.aspx") Dim feed11 As Task(Of FeedData) = GetFeedAsync("http://blogs.windows.com/ie/b/ie/atom.aspx") Dim feed12 As Task(Of FeedData) = GetFeedAsync("http://blogs.windows.com/windows_phone/b/wpdev/atom.aspx") Dim feed13 As Task(Of FeedData) = GetFeedAsync("http://blogs.windows.com/windows_phone/b/wmdev/atom.aspx") Dim feed14 As Task(Of FeedData) = GetFeedAsync("http://blogs.windows.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(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 IsNot Nothing AndAlso 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 matches = _feedDataSource.Feeds. Where(Function(group) group IsNot Nothing). 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
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
Build date: 3/11/2013