Windows Phone Hub App With JSON Data

Introduction

Welcome again! Today, I'm going to talk about handling data in JavaScript Object Notation (JSON) format and we'll be using the Windows Phone “Hub App” template. It's going to be fun to work with this awesome template and I hope after exploring the “Hub App” and “JSON Data”, you'll be able to do your own stuff and write a great Windows Phone App. If you have followed my previous articles, as a great Windows Phone developer your journey starts here. We'll create an awesome app called “Letters of John Keats”. JK is one of my favorite poets and we're going to make this app that will have the letters to his girlfriend “Fanny Brawne”. So let's get cracking on “Hub App” working with “JSON”.

Creating a New Project

First of all create a new project and select the “Hub App” template. Provide it the name “HubApp”.

hub app
                                                                              Figure 1

You now have all the following files in your Solution Explorer.

soluction explorer
                                                Figure 2

Working with JSON Data

So, first is first, we'll replace the “SampleData.json” with our own file. The simple way to do that is to erase all the data in the existing file and paste your data there. We will replace it with our own data here.

  1. {"Groups":[  
  2.     {  
  3.         "Title""Letters of John Keats",  
  4.         "Subtitle""Selected Love Letters to Fanny Brawne",  
  5.         "Items": [  
  6.             {  
  7.                 "Title""July 3, 1819",  
  8.                 "Subtitle""Shanklin, Isle of Wight, Thursday",  
  9.                 "Content""My dearest Lady - I am glad I had ... please so."  
  10.             }  
  11.         ]  
  12.     }  
  13. ]  
  14. }  
Listing 1

Here is sample data for our application. We've used the JSON format. JSON is a lightweight data interchange format. If you notice, you can realize that “JSON” is nothing but an “Array” object. Here, the “Items” has two items and the items are surrounded by square brackets (“[]”), the last item doesn't have a comma at the end in line number 15. Mainly every last element doesn't need a comma at the end. You can declare as many items as you need. You can also have many group items. This is the basic format of “JSON”. You can learn the basics of JSON at: Introducing JSON.

Retrieving the JSON Data

So, our app local data is set, now we need to modify the class “SampleDataSouce.cs” like this.
  1. // Sample Data Item Class  
  2. public class SampleDataItem  
  3. {  
  4.     public SampleDataItem(String title, String subtitle, String content)  
  5.     {  
  6.         this.Title = title;  
  7.         this.Subtitle = subtitle;  
  8.         this.Content = content;  
  9.     }  
  10.   
  11.     public string Title { getprivate set; }  
  12.     public string Subtitle { getprivate set; }  
  13.     public string Content { getprivate set; }  
  14.   
  15.     public override string ToString()  
  16.     {  
  17.         return this.Title;  
  18.     }  
  19. }  
  20.   
  21. // Sample Data Group Class  
  22. public class SampleDataGroup  
  23. {  
  24.     public SampleDataGroup(String title, String subtitle)  
  25.     {  
  26.         this.Title = title;  
  27.         this.Subtitle = subtitle;  
  28.         this.Items = new ObservableCollection<SampleDataItem>();  
  29.     }  
  30.   
  31.     public string Title { getprivate set; }  
  32.     public string Subtitle { getprivate set; }  
  33.     public ObservableCollection<SampleDataItem> Items { getprivate set; }  
  34.   
  35.     public override string ToString()  
  36.     {  
  37.         return this.Title;  
  38.     }  
  39. }  
  40.   
  41. public sealed class SampleDataSource  
  42. {  
  43.     private static SampleDataSource _sampleDataSource = new SampleDataSource();  
  44.   
  45.     private ObservableCollection<SampleDataGroup> _groups = new ObservableCollection<SampleDataGroup>();  
  46.     public ObservableCollection<SampleDataGroup> Groups  
  47.     {  
  48.         get { return this._groups; }  
  49.     }  
  50.   
  51.     public static async Task<IEnumerable<SampleDataGroup>> GetGroupsAsync()  
  52.     {  
  53.         await _sampleDataSource.GetSampleDataAsync();  
  54.         return _sampleDataSource.Groups;  
  55.     }  
  56.   
  57.     public static async Task<SampleDataGroup> GetGroupAsync(string uniqueId)  
  58.     {  
  59.         await _sampleDataSource.GetSampleDataAsync();  
  60.         // Simple linear search is acceptable for small data sets  
  61.         var matches = _sampleDataSource.Groups.Where((group) => group.Title.Equals(uniqueId));  
  62.         if (matches.Count() == 1) return matches.First();  
  63.         return null;  
  64.     }  
  65.   
  66.     public static async Task<SampleDataItem> GetItemAsync(string uniqueId)  
  67.     {  
  68.         await _sampleDataSource.GetSampleDataAsync();  
  69.         // Simple linear search is acceptable for small data sets  
  70.         var matches = _sampleDataSource.Groups.SelectMany(group => group.Items).Where((item) => item.Title.Equals(uniqueId));  
  71.         if (matches.Count() == 1) return matches.First();  
  72.         return null;  
  73.     }  
  74.   
  75.     private async Task GetSampleDataAsync()  
  76.     {  
  77.         if (this._groups.Count != 0)  
  78.             return;  
  79.   
  80.         Uri dataUri = new Uri("ms-appx:///DataModel/SampleData.json");  
  81.   
  82.         StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(dataUri);  
  83.         string jsonText = await FileIO.ReadTextAsync(file);  
  84.         JsonObject jsonObject = JsonObject.Parse(jsonText);  
  85.         JsonArray jsonArray = jsonObject["Groups"].GetArray();  
  86.   
  87.         foreach (JsonValue groupValue in jsonArray)  
  88.         {  
  89.             JsonObject groupObject = groupValue.GetObject();  
  90.             SampleDataGroup group = new SampleDataGroup(groupObject["Title"].GetString(),  
  91.                                                         groupObject["Subtitle"].GetString());  
  92.   
  93.             foreach (JsonValue itemValue in groupObject["Items"].GetArray())  
  94.             {  
  95.                 JsonObject itemObject = itemValue.GetObject();  
  96.                 group.Items.Add(new SampleDataItem(itemObject["Title"].GetString(),  
  97.                                                    itemObject["Subtitle"].GetString(),  
  98.                                                    itemObject["Content"].GetString()));  
  99.             }  
  100.             this.Groups.Add(group);  
  101.         }  
  102.     }  
  103. }  
Different JSON Approach

Another approach of “JSON” you can have is given below.
  1. {"Groups":[  
  2.     {  
  3.         "Title""Letters of John Keats",  
  4.         "Subtitle""Selected Love Letters to Fanny Brawne",  
  5.         "Items": [  
  6.             {  
  7.                 "Title""July 3, 1819",  
  8.                 "Subtitle""Shanklin, Isle of Wight, Thursday",  
  9.                 "Content":   
  10.                 [  
  11.                     "My dearest Lady - I am glad I had ... little mad.",  
  12.                     ...  
  13.                     "Present my Compliments to your mother, ... so."  
  14.                 ]  
  15.             }  
  16.         ]  
  17.     }  
  18. ]  
  19. }  
Listing 3

Then, you need to change this line of code in “SampleDataSouce.cs”.
  1. foreach (JsonValue itemValue in groupObject["Items"].GetArray())  
  2. {  
  3.     JsonObject itemObject = itemValue.GetObject();  
  4.     group.Items.Add(new SampleDataItem(itemObject["Title"].GetString(),  
  5.                                        itemObject["Subtitle"].GetString(),  
  6.                                        itemObject["Content"].Stringify().Replace("[""").Replace("]""").Replace("\",""\n").Replace("\"""")));  
  7. }  
Listing 4

I personally don't like to do that, because you can't use double quotes and “\n” or “\r” in this case. Or you may find it helpful in some cases.

Working with “HubPage.xaml”

Now, we'll modify the “HubPage.xaml” first. We don't need the other sections of “HubPage.xaml” for our application.
  1. <Page.Resources>  
  2.     <DataTemplate x:Key="HubSectionHeaderTemplate">  
  3.         <TextBlock Margin="0,0,0,-9.5" Text="{Binding}"/>  
  4.     </DataTemplate>  
  5. </Page.Resources>  
  6.   
  7. <Grid x:Name="LayoutRoot">  
  8.     <Hub x:Name="Hub" x:Uid="Hub" Header="application name" Background="{ThemeResource HubBackgroundImageBrush}">  
  9.         <HubSection x:Uid="HubSection1" Header="{Binding Subtitle}" DataContext="{Binding Groups[0]}" HeaderTemplate="{ThemeResource HubSectionHeaderTemplate}" Width="400">  
  10.             <DataTemplate>  
  11.                 <ListView  
  12.                     ItemsSource="{Binding Items}"  
  13.                     IsItemClickEnabled="True"  
  14.                     ItemClick="ItemView_ItemClick"  
  15.                     ContinuumNavigationTransitionInfo.ExitElementContainer="True">  
  16.                     <ListView.ItemTemplate>  
  17.                         <DataTemplate>  
  18.                             <StackPanel Grid.Column="1" Margin="14.5,0,0,0">  
  19.                                 <TextBlock Text="{Binding Title}" Style="{ThemeResource ListViewItemTextBlockStyle}"/>  
  20.                                 <TextBlock Padding="10" Text="{Binding Subtitle}" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}"/>  
  21.                                 <Line  x:Name="line" X1="0" Y1="5" X2="365" Y2="5"  Stroke="Brown" StrokeThickness="2"></Line>  
  22.                             </StackPanel>  
  23.                         </DataTemplate>  
  24.                     </ListView.ItemTemplate>  
  25.                 </ListView>  
  26.             </DataTemplate>  
  27.         </HubSection>  
  28.     </Hub>  
  29. </Grid>  
Listing 5

Let me explain what I've done here. In line number 9, you can see that we've bound the header element with “Subtitle”. It's actually the “Groups'” subtitle because our “Datacontext” is “Groups[0]” index, the first group content. In line number {??} we've bound “ItemSource” to “Items”, so it'll fetch all the “Items” data. And in line number 14 is a a click event named “ItemView_ItemClick”. When you click an item, it'll bring the “ItemPage.xaml” to view the details of Items. In line numbers 19 & 20 we bound the value “Title” and “Subtitle”. Line number 21 uses a line to separate the items title and subtitle from other items.

application
                                 Figure 3

Now if we look at the “HubPage.xaml.cs”, we just modify the “ItemView_ItemClick” event like this.
  1. private void ItemView_ItemClick(object sender, ItemClickEventArgs e)  
  2. {  
  3.     // Navigate to the appropriate destination page, configuring the new page  
  4.     // by ing required information as a navigation parameter  
  5.     var itemTitle = ((SampleDataItem)e.ClickedItem).Title;  
  6.     if (!Frame.Navigate(typeof(ItemPage), itemTitle))  
  7.     {  
  8.         throw new Exception(this.resourceLoader.GetString("NavigationFailedExceptionMessage"));  
  9.     }  
  10. }  
Listing 6

Here in line number 5, we declare a variable “itemTitle” and set it to the title of “Items” and it using the “Frame.Navigation()” as a parameter in line number 6. We don't need the “GroupSection_ItemClick” event because we aren't using “SectionPage.xaml” in our application. So we're working on just two pages, the first is “HubPage.xaml” and the second is “ItemPage.xaml”. So, you can understand that you have some real power to present a lot of data simply in two pages. So DataBinding and JSON gives us lots of flexibility to make our apps much faster and efficient.

Working with “ItemPage.xaml”

We will now modify our “ItemPage.xaml”, just use these three lines of code.
  1. <ScrollViewer>  
  2.     <StackPanel Grid.Column="1" Margin="14.5,0,0,0">  
  3.         <TextBlock Text="{Binding Title}" Style="{ThemeResource ListViewItemTextBlockStyle}"/>  
  4.         <TextBlock Padding="10,0,0,20" Text="{Binding Subtitle}" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}"/>  
  5.         <TextBlock Padding="0,0,0,10" TextWrapping="Wrap" Text="{Binding Content}" FontSize="20" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}"/>  
  6.     </StackPanel>  
  7. </ScrollViewer>  
Listing 7

Here, then we've three TextBlocks and the first one is showing the items “Title”, the second one is “Subtitle” and the third one is “Content” that contains the letter body. We surround the TextBlocks with a StackPanel and ScrollViewer so that you can see the long text with the scrolling option. One important thing is in line number 5 we've used TextWrapping to “Wrap” so that the text fit in the window size.

Working with “Sectionpage.xaml”

One more extra thing you can do is to modify your “SectionPage.xaml”. Though I'm not using this page, just showing it if you do want to use it. Modify the “SectionPage.xaml” like this, here is only “ListView”.
  1. <ListView  
  2.     x:Name="itemListView"  
  3.     AutomationProperties.AutomationId="ItemListView"  
  4.     AutomationProperties.Name="Items In Group"  
  5.     TabIndex="1"  
  6.     Grid.Row="1"  
  7.     ItemsSource="{Binding Items}"  
  8.     IsItemClickEnabled="True"  
  9.     ItemClick="ItemView_ItemClick"  
  10.     SelectionMode="None"  
  11.     IsSwipeEnabled="false"  
  12.     Margin="19,0,0,0">  
  13.     <ListView.ItemTemplate>  
  14.         <DataTemplate>  
  15.             <Grid>  
  16.                 <Grid.ColumnDefinitions>  
  17.                     <ColumnDefinition Width="Auto"/>  
  18.                     <ColumnDefinition Width="*"/>  
  19.                 </Grid.ColumnDefinitions>  
  20.   
  21.                 <StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0">  
  22.                     <TextBlock Text="{Binding Title}" Style="{ThemeResource ListViewItemTextBlockStyle}"/>  
  23.                     <TextBlock Text="{Binding Subtitle}" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}"/>  
  24.                 </StackPanel>  
  25.             </Grid>  
  26.         </DataTemplate>  
  27.     </ListView.ItemTemplate>  
  28. </ListView>  
Listing 8

We just used the “Title” and “Subtitle” sections. Also the “ItemView_ItemClick” event in “SectionPage.xaml.cs” like this.
  1. private void ItemView_ItemClick(object sender, ItemClickEventArgs e)  
  2. {  
  3.     var itemTitle = ((SampleDataItem)e.ClickedItem).Title;  
  4.     if (!Frame.Navigate(typeof(ItemPage), itemTitle))  
  5.     {  
  6.         var resourceLoader = ResourceLoader.GetForCurrentView("Resources");  
  7.         throw new Exception(resourceLoader.GetString("NavigationFailedExceptionMessage"));  
  8.     }  
  9. }  
Listing 9

We've declared a variable “itemTitle” and ed it using navigation. That's it.

Working with Phone Resources

Now change the “Header.Text” and “Hub.Header” in “Strings>>en-US>>Resources.resw” like this.

Working with Phone Resources
                                                Figure 4

Working with “App.xaml”

Also, we want to change the background of our app, so that it looks more beautiful and readable. Go to “App.xaml” and change the background as in the following.

  1. <Application.Resources>  
  2.     <ResourceDictionary>  
  3.         <ResourceDictionary.ThemeDictionaries>  
  4.             <ResourceDictionary x:Key="Default">  
  5.                 <ImageBrush x:Key="HubBackgroundImageBrush" ImageSource="Assets/HubBackground.theme-light.png" Opacity="0.3"/>  
  6.             </ResourceDictionary>  
  7.             <ResourceDictionary x:Key="HighContrast">  
  8.                 <ImageBrush x:Key="HubBackgroundImageBrush" ImageSource="{x:Null}"/>  
  9.             </ResourceDictionary>  
  10.         </ResourceDictionary.ThemeDictionaries>  
  11.   
  12.     </ResourceDictionary>  
  13. </Application.Resources>  
Listing 10

Here, we change the background of the app, just by changing the picture. You'll find it in the “Assets” folder or you can upload your own picture. Also, we changed the opacity to “0.3” so the background becomes darker than it really is.

Now your design should look like this.

Running the Application
                                                                           Figure 5

Running the Application

Now we're all set. If we run the application, it looks just awesome like this.

output                                                                                    Figure 6
Summary

So, we just made a rich “JSON Data Hub” application by doing a few modifications of the “Hub App” template. I personally made an app about my favorite poet John Keats' letters to his girlfriend Fanny Brawne and you can make your own data bound app like this.

Hopefully you've enjoyed this. That's it for today. I'll be here with a new topic soon. Until then good bye. Have a nice day.

Happy Coding!

Read the original article at: Hub App - Working with JSON Data.
 
 


Similar Articles