📜 ⬆️ ⬇️

We understand the development of Windows 8 applications on XAML / С #, implementing a simple RSS Reader. Part 2


We continue to develop a simple RSS Reader. A start was made in the article Understanding the development of Windows 8 applications on XAML / #, implementing a simple RSS Reader. Part 1 , where we created the project received RSS data and started to make beautiful. In this part we will add beauty and functionality to our reading room.

We continue to do beautifully


Now we have beautiful tiles of different sizes, and we can, if desired, tile in different groups. Let's do it. We will do the blog of Stas Pavlov with tiles of different sizes, and for Sergey Pugachev's Blog we will not spoil the user with such diversity.

How to do it? Everything is very simple. The logic that determines the size of the tiles is all implemented in the PrepareContainerForItemOverride function of the VariableSizeGridView class, so that you can add the appropriate logic there.
')
To distinguish groups, we will use UniqueID, for the group it corresponds to the URL to RSS. Add the following code to the PrepareContainerForItemOverride function:
int group = -1; if (dataItem.Group.UniqueId.Contains("stas")) { group = 1; } 


And now we will change the behavior of the function, depending on which group it works for. adding a condition.
 if (group > 0) { if (index == 2) { colVal = 2; rowVal = 4; } if (index == 5) { colVal = 4; rowVal = 4; } } 


Run the program to check how it now works.


We set ourselves an even more difficult task. And what if we need to use different display templates for display in general? This is also a solvable problem. We will again have to implement our own class, which will contain logic, but now it will be inherited from DataTemplateSelector.

So, let's add a new class named MyDataTemplateSelector to the solution, indicating that it inherits from DataTemplateSelector. Add in using directives:
 using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; 

And override the function SelectTemplateCore. The result should be the following:
 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace MyReader { class MyDataTemplateSelector : DataTemplateSelector { protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) { return base.SelectTemplateCore(item, container); } } } 

Now you need to define in the XAML file those templates from which we will choose. To do this, open GroupedItemsPage.xaml and go to the resources of the page, where we have the CustomItemTemplate template defined:
 <DataTemplate x:Key="CustomItemTemplate"> <Grid HorizontalAlignment="Left"> <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}"> <Image Source="{Binding Image}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/> </Border> <StackPanel Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}" VerticalAlignment="Bottom"> <TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Height="90" Margin="15,0,15,0" FontSize="30" /> </StackPanel> </Grid> </DataTemplate> 

Define another template with minimal changes - change the alignment:
 <DataTemplate x:Key="CustomItemTemplate2"> <Grid HorizontalAlignment="Right"> <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}"> <Image Source="{Binding Image}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/> </Border> <StackPanel Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}" VerticalAlignment="Top"> <TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Height="90" Margin="15,0,15,0" FontSize="30" /> </StackPanel> </Grid> </DataTemplate> 


Let us now return to our MyDataTemplateSelector class and add code that determines which template to use, depending on which element of the group is displayed:
 using MyReader.Data; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace MyReader { class MyDataTemplateSelector : DataTemplateSelector { public DataTemplate Template1 { get; set; } public DataTemplate Template2 { get; set; } protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) { RSSDataItem dataItem = item as RSSDataItem; if (dataItem.Group.UniqueId.Contains("stas")) { return Template1; } else return Template2; } } } 


Go back to GroupedItemsPage.xaml and go to the resources page, where we have defined templates and initialize our selector:
 <local:MyDataTemplateSelector x:Key="MyDataSelector" Template1="{StaticResource CustomItemTemplate}" Template2="{StaticResource CustomItemTemplate2}"/> 
And we specify the selector in instead of specifying the template for the Item for local: VariableSizeGridView:
 <local:VariableSizeGridView x:Name="itemGridView" AutomationProperties.AutomationId="ItemGridView" AutomationProperties.Name="Grouped Items" Grid.RowSpan="2" Padding="116,137,40,46" ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}" ItemTemplateSelector="{StaticResource MyDataSelector}" SelectionMode="None" IsSwipeEnabled="false" IsItemClickEnabled="True" ItemClick="ItemView_ItemClick"> 


Run the application to make sure everything works as planned.


Great, everything works as planned, you can go to work with live tiles.

But, before moving on to live tiles, let's change the text style of the caption on the tiles of the group.

Create, on the basis of the BasicTextStyle style, the styles we need and place them in the resources of the GroupedItemsPage.xaml page:
 <Style x:Key="ExtendedTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BasicTextStyle}"> <Setter Property="LineHeight" Value="40"/> <Setter Property="LineStackingStrategy" Value="BlockLineHeight"/> <!-- Properly align text along its baseline --> <Setter Property="RenderTransform"> <Setter.Value> <TranslateTransform X="-1" Y="4"/> </Setter.Value> </Setter> </Style> <Style x:Key="ExtendedTitleTextStyle" TargetType="TextBlock" BasedOn="{StaticResource ExtendedTextStyle}"> <Setter Property="FontWeight" Value="SemiBold"/> </Style> 


And we will impose this style on the text in our templates ::
 <DataTemplate x:Key="CustomItemTemplate"> <Grid HorizontalAlignment="Left"> <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}"> <Image Source="{Binding Image}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/> </Border> <StackPanel Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}" VerticalAlignment="Bottom"> <TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource ExtendedTitleTextStyle}" Height="90" Margin="15,0,15,0" FontSize="30" /> </StackPanel> </Grid> </DataTemplate> <DataTemplate x:Key="CustomItemTemplate2"> <Grid HorizontalAlignment="Right"> <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}"> <Image Source="{Binding Image}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/> </Border> <StackPanel Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}" VerticalAlignment="Top"> <TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource ExtendedTitleTextStyle}" Height="90" Margin="15,0,15,0" FontSize="30" /> </StackPanel> </Grid> </DataTemplate> 


Launch the application and see how the signatures on grouped elements now look.


Everything looks much better. If there is a desire, you can play with styles, achieving the desired effect.

Add live tiles


It's time to add live tiles. As long as the carrier does not have a service that keeps track of updates, our tiles will be updated at the time of receiving the RSS to please the user until the next launch of the application.

Go to the RSSDataSource.cs file and add the UpdateTile method to the RSSDataSource class:
 public static void UpdateTile() { var news = RSSDataSource.AllGroups[0].Items.ToList(); var xml = new XmlDocument(); xml.LoadXml( string.Format( @"<?xml version=""1.0"" encoding=""utf-8"" ?> <tile> <visual branding=""none""> <binding template=""TileSquarePeekImageAndText03""> <image id=""1"" src=""ms-appx:///Assets/Logo.png"" alt=""alt text""/> <text id=""1"">{0}</text> <text id=""2"">{1}</text> <text id=""3"">{2}</text> <text id=""4"">{3}</text> </binding> <binding template=""TileWidePeekImageAndText02""> <image id=""1"" src=""ms-appx:///Assets/Habr_WideLogo.png"" alt=""alt text""/> <text id=""1"">{0}</text> <text id=""2"">{1}</text> <text id=""3"">{2}</text> <text id=""4"">{3}</text> </binding> </visual> </tile>", news.Count > 0 ? System.Net.WebUtility.HtmlEncode(news[0].Title) : "", news.Count > 1 ? System.Net.WebUtility.HtmlEncode(news[1].Title) : "", news.Count > 2 ? System.Net.WebUtility.HtmlEncode(news[2].Title) : "", news.Count > 3 ? System.Net.WebUtility.HtmlEncode(news[3].Title) : "")); TileUpdateManager.CreateTileUpdaterForApplication().Update(new TileNotification(xml)); } 

Do not forget to add the following directives to the using block:
 using Windows.Data.Xml.Dom; using Windows.UI.Notifications; 

Here we create XML for updating tiles using templates, and actually update the tiles themselves. The code is completely transparent. Since this is an example, I always take just the first RSS feed.

For this to work, you need to add a call to this method to any place where RSS is already available. Let's add await to the AddGroupForFeedAsync called RSS download methods and then we can safely call our function after adding the first feed.

Go to the LoadState method in the GroupedItemsPage.xaml.cs file, add async to it, addGroupForFeedAsync methods and add the UpdateTile :: call
 protected async override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState) { this.DefaultViewModel["Groups"] = RSSDataSource.AllGroups; await RSSDataSource.AddGroupForFeedAsync("http://blogs.msdn.com/b/stasus/rss.aspx"); RSSDataSource.UpdateTile(); RSSDataSource.AddGroupForFeedAsync("http://www.spugachev.com/feed"); } 

I deliberately put aside one call without await — later — notice how it looks when the application starts.

Now it remains to add support for WideLogo to the application. To do this, create a file Habr_WideLogo.scale-100.png 310 by 150 in size, add it to the Asset folder of the project. Then double-click on the Package.appxmanifest file to open its visual editor and add WideLogo to the application:


Now we are fully ready to launch the application. Run it, then close it. Go to the start screen and make sure that the live tiles work, moreover, both square and rectangular!

It's time to add contracts. Let's start with the Share contract. Implement the data source. The data will be flipped on the RSS post page, providing the system with the maximum possible amount of data.

Let's go to the page code ItemDetailPage.xaml.cs. In order to provide data to the system, it is necessary to handle the DataRequested event for the DataTransferManager. So, let's begin.

Add a contract Share


Let's register the DataRequested event handler in the NavigateTo page (and unsubscribe from the event in NavigateFrom), and implement the handler in which we provide the system with the post name and text:
 protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); DataTransferManager.GetForCurrentView().DataRequested += Share_DataRequested; } protected override void OnNavigatedFrom(NavigationEventArgs e) { base.OnNavigatedFrom(e); DataTransferManager.GetForCurrentView().DataRequested -= Share_DataRequested; } private void Share_DataRequested(DataTransferManager sender, DataRequestedEventArgs args) { var selectedItem = (RSSDataItem)this.flipView.SelectedItem; args.Request.Data.Properties.Title = selectedItem.Title; args.Request.Data.Properties.Description = selectedItem.Content; args.Request.Data.SetText(selectedItem.Content); } 

Run the application, go to the post page and check that the application can now transfer data to other applications.


In fact, we get much more data for sharing in the RSS feed. This is a picture of a post, a post URI, etc. I propose to independently modify the code of the method of adding the feed, as well as the related classes, so that there is more data. More data - with more applications you can share!

The sudden desire to tell about DataTemplateSelector made the article already quite large. Therefore, it is necessary to do the third part. In it we will transfer the search and setting contract, if it works out - parallax of the background and other useful things, and if it doesn’t fit, I will make several more parts.

The current application code can be downloaded from SkyDrive via a short link: aka.ms/w8RSSp2

UPD:
Part of the 1st cycle
Part of the 3rd cycle

Source: https://habr.com/ru/post/163837/


All Articles