Working With the New Hub Control in Windows 8.1

Introduction

At Build 2013, Microsoft’s annual conference targeted for developers, Microsoft unveiled over 5000 new APIs and a bunch of new UI controls slated to arrive to users as the next release of Windows, called Windows 8.1. This release, which is going to be a free update to Windows 8 users, is intended to bring even better experiences for Windows users as well as Windows developers.

The Hub control is a new control, which was announced as part of Windows 8.1. The Hub control makes it easy for Windows Store developers to create the hub design pattern for their application, which adheres to the Windows Store design guidelines.

Hub Control

The Hub control is ideal for applications that have either have a large collection of content or distinct sections of content.

The premise of hub design is to separate the content into distinct sections and make the hub page the landing page the user would see when the application is invoked. Hub control supports displaying the content in either horizontally or vertically panning views.

Windows 8.1 offers the hub control both as a XAML control as well as JavaScript control. The XAML control resides in the Windows.UI.Xaml.Controls namespace. The JavaScript control resides in the WinJS.UI namespace in the Ui.js library.

The XAML Hub control is different from GridView and ListView XAML controls because it allows you to display data from more than one source while the GridView and ListView can only operate with data from a single source. Microsoft has made it very easy to create a Hub application by providing a dedicated project template for a Hub application.

The Hub controls supports a header, which is used to let the users know the context of your hub. If the simple Windows.UI.Xaml.Controls.Hub,Header is not sufficient, one can define a HubTemplate.

The content of hub needs to be put in the HubSection controls.

Hands On

Now, we will try to build a simple Hub Control application. You will need Visual Studio 2013 Express installed for this demo.

Create a new Windows 8.1 project of type “Hub App” titled Win8.1HubControlDemo.

Create a new Windows 8.1 project
Create a new Windows 8.1 project

You will notice that Visual Studio Express 2013 creates a page titled HubPage.xaml.

Open up the XAML behind the page.

//HubPage.xaml
<Page
    x:Name="pageRoot"
    x:Class="Windows8._1HubControlDemo.HubPage"
    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:Windows8._1HubControlDemo"
    xmlns:data="using:Windows8._1HubControlDemo.Data"
    xmlns:common="using:Windows8._1HubControlDemo.Common"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
 
    <Page.Resources>
        <common:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
        <!--
        Collection of grouped items displayed by this page, bound to a subset
        of the complete item list because items in groups cannot be virtualized
    -->
        <CollectionViewSource
        x:Name="groupedItemsViewSource"
        Source="{Binding Groups}"
        ItemsPath="TopItems"
        d:Source="{Binding Groups, Source={d:DesignData Source=/DataModel/SampleData.json, Type=data:SampleDataSource}}"/>
 
        <!-- Grid-appropriate 310 by 260 pixel item template as seen in section 4 -->
        <DataTemplate x:Key="Standard310x260ItemTemplate">
            <Grid Height="250" Width="310" Margin="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Height="150">
                    <Image Source="{Binding ImagePath}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
                </Border>
                <StackPanel Grid.Row="1" Margin="0,10,0,0">
                    <TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/>
                    <TextBlock Text="{Binding Description}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />
                </StackPanel>
            </Grid>
        </DataTemplate>
 
        <DataTemplate x:Key="Standard420x130ItemTemplate">
            <Grid Height="110" Width="420" Margin="10">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="110" Height="110">
                    <Image Source="{Binding ImagePath}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
                </Border>
                <StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0">
                    <TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/>
                    <TextBlock Text="{Binding Subtitle}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
                    <TextBlock Text="{Binding Description}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60"/>
                </StackPanel>
            </Grid>
        </DataTemplate>
    </Page.Resources>
 
    <!--
    This grid acts as a root panel for the page.
  -->
    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Grid.ChildrenTransitions>
            <TransitionCollection>
                <EntranceThemeTransition/>
            </TransitionCollection>
        </Grid.ChildrenTransitions>
        <Hub SectionHeaderClick="Hub_SectionHeaderClick" Padding="40,40,0,0">
            <Hub.Header>
                <!-- Back button and page title -->
                <Grid Margin="0,20,0,0">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="80"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <StackPanel Height="40">
                        <AppBarButton x:Name="backButton" Icon="Back" Margin="-30,-14,0,0"
                              Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}" 
                              Visibility="{Binding IsEnabled, Converter={StaticResource BooleanToVisibilityConverter}, RelativeSource={RelativeSource Mode=Self}}"
                              AutomationProperties.Name="Back"
                              AutomationProperties.AutomationId="BackButton"
                              AutomationProperties.ItemType="Navigation Button"/>
                    </StackPanel>
                    <TextBlock x:Name="pageTitle" Text="{StaticResource AppName}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1" 
                       IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Top"/>
                </Grid>
            </Hub.Header>
            <HubSection Width="780">
                <HubSection.Background>
                    <ImageBrush ImageSource="Assets/MediumGray.png" Stretch="UniformToFill" />
                </HubSection.Background>
            </HubSection>
            <HubSection Width="580" Padding="120,30,40,44"  VerticalAlignment="Top" >
                <HubSection.Header>
                    <TextBlock x:Uid="Section1Header" TextLineBounds="TrimToBaseline" OpticalMarginAlignment="TrimSideBearings" Text="Section 1"/>
                </HubSection.Header>
                <DataTemplate>
                    <Grid Margin="0,10,0,0">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <Image Source="Assets/MediumGray.png" Stretch="Fill" Width="420" Height="280"/>
                        <TextBlock Grid.Row="1" x:Uid="Section1Subtitle" Style="{StaticResource SubheaderTextBlockStyle}" TextWrapping="Wrap"  Margin="0,10,0,0" Text="Lorem ipsum dolor sit nonumy sed consectetuer ising elit, sed diam"/>
                        <TextBlock Grid.Row="2" x:Uid="DescriptionHeader" Margin="0,10,0,0" Style="{StaticResource TitleTextBlockStyle}" Text="Description text:"/>
                        <TextBlock Grid.Row="3" x:Uid="Section1DescriptionText" Style="{StaticResource BodyTextBlockStyle}" Text="Lorem ipsum dolor sit amet, consectetuer ising elit, sed diam nonummy nibh uismod tincidunt ut laoreet suscipit lobortis ni ut wisi quipexerci quis consequat minim veniam, quis nostrud exerci tation ullam corper. Lorem ipsum dolor sit amet, consectetuer ising elit, sed diam nonummy nibh uismod tincidunt ut laoreet suscipit lobortis ni ut wisi quipexerci quis consequat minim veniam, quis nostrud exerci tation ullam corper. "/>
                    </Grid>
                </DataTemplate>
            </HubSection>
            <HubSection Padding="40,30,40,44" DataContext="{Binding Path=[0], Source={StaticResource groupedItemsViewSource}}" IsHeaderInteractive="True" >
                <HubSection.Header>
                    <TextBlock x:Uid="Section2Header" TextLineBounds="TrimToBaseline" OpticalMarginAlignment="TrimSideBearings" Text="Section 2"/>
                </HubSection.Header>
                <DataTemplate>
                    <ListView
                        x:Name="itemListView"
                        Margin="-14,-4,0,0"
                        AutomationProperties.AutomationId="ItemListView"
                        AutomationProperties.Name="Grouped Items"
                        ItemsSource="{Binding Items}"
                        ItemTemplate="{StaticResource Standard420x130ItemTemplate}"
                        IsSwipeEnabled="False"
                        IsItemClickEnabled="True"
                        ScrollViewer.VerticalScrollBarVisibility="Hidden"
                        SelectionMode="None"
                        ItemClick="ItemView_ItemClick">
                        <ListView.ItemsPanel>
                            <ItemsPanelTemplate>
                                <ItemsWrapGrid />
                            </ItemsPanelTemplate>
                        </ListView.ItemsPanel>
                    </ListView>
                </DataTemplate>
            </HubSection>
            <HubSection Padding="7,30,40,44">
                <HubSection.Header>
                    <TextBlock x:Uid="Section3Header" TextLineBounds="TrimToBaseline" OpticalMarginAlignment="TrimSideBearings" Text="Section 3"/>
                </HubSection.Header>
                <DataTemplate>
                    <!-- width of 400 -->
                    <StackPanel Orientation="Vertical" Margin="2,10,0,0">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="130"/>
                                <ColumnDefinition Width="5"/>
                                <ColumnDefinition Width="130"/>
                                <ColumnDefinition Width="5"/>
                                <ColumnDefinition Width="130"/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="270"/>
                                <RowDefinition Height="95"/>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="*" />
                            </Grid.RowDefinitions>
                            <Image Grid.ColumnSpan="5" Source="Assets/MediumGray.png" Stretch="Fill" Margin="0,0,0,10"/>
                            <Image Grid.Row="1" Source="Assets/MediumGray.png" Stretch="Fill"/>
                            <Image Grid.Row="1" Grid.Column="2" Source="Assets/MediumGray.png" Stretch="Fill"/>
                            <Image Grid.Row="1" Grid.Column="4" Source="Assets/MediumGray.png" Stretch="Fill"/>
                            <TextBlock Grid.Row="2" Grid.ColumnSpan="5" x:Uid="DescriptionHeader" Margin="0,15,0,0" Style="{StaticResource TitleTextBlockStyle}"/>
                            <TextBlock Grid.Row="3" Grid.ColumnSpan="5" x:Uid="LongText" Style="{StaticResource BodyTextBlockStyle}"/>
                        </Grid>
                    </StackPanel>
                </DataTemplate>
            </HubSection>
            <HubSection Width="520" Padding="40,30,40,44">
                <HubSection.Header>
                    <TextBlock x:Uid="Section4Header" TextLineBounds="TrimToBaseline" OpticalMarginAlignment="TrimSideBearings" Text="Section 4"/>
                </HubSection.Header>
                <DataTemplate>
                    <Grid Margin="2,10,0,0">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <TextBlock x:Uid="ItemTitle" Margin="0,0,0,10" Style="{StaticResource TitleTextBlockStyle}" Text="Item Title" />
                        <TextBlock Grid.Row="1" x:Uid="Section4UnderTitle" Style="{StaticResource SubheaderTextBlockStyle}" Text="Quisque in porta lorem dolor amet sed consectetuer ising elit, sed diam non my nibh uis mod wisi quip."/>
                        <TextBlock Grid.Row="2" x:Uid="ItemSubTitle" Margin="0,20,0,0" Style="{StaticResource SubtitleTextBlockStyle}" Text="Item Sub Title"/>
                        <TextBlock Grid.Row="3" x:Uid="LongText" Style="{StaticResource BodyTextBlockStyle}" Text="Lorem ipsum dolor sit amet, consectetuer ising elit, sed diam nonummy nibh uismod tincidunt ut laoreet suscipit lobortis ni ut wisi quipexerci quis consequat minim veniam, quis nostrud exerci tation ullam corper. Lorem ipsum dolor sit amet, consectetuer ising elit, sed diam nonummy nibh uismod tincidunt ut laoreet suscipit lobortis ni ut wisi quipexerci quis consequat minim veniam, quis nostrud exerci tation ullam corper."/>
                    </Grid>
                </DataTemplate>
            </HubSection>
            <HubSection DataContext="{Binding Path=[5], Source={StaticResource groupedItemsViewSource}}"  Padding="40,30,150,44">
                <HubSection.Header>
                    <TextBlock x:Uid="Section5Header" TextLineBounds="TrimToBaseline" OpticalMarginAlignment="TrimSideBearings" Text="Section 5"/>
                </HubSection.Header>
                <DataTemplate>
                    <GridView
                        x:Name="itemGridView"
                        Margin="-13,-4,0,0"
                        AutomationProperties.AutomationId="ItemGridView"
                        AutomationProperties.Name="Items In Group"
                        ItemsSource="{Binding Items}"
                        ItemTemplate="{StaticResource Standard310x260ItemTemplate}"
                        SelectionMode="None"
                        IsSwipeEnabled="false"
                        IsItemClickEnabled="True"
                        ItemClick="ItemView_ItemClick">
                    </GridView>
                </DataTemplate>
            </HubSection>
        </Hub>
    </Grid>
</Page>

Now, we will update the header for the hub.

We can see that the header is defined as under.

<Hub.Header>
                <!-- Back button and page title -->
                <Grid Margin="0,20,0,0">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="80"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <StackPanel Height="40">
                        <AppBarButton x:Name="backButton" Icon="Back" Margin="-30,-14,0,0"
                              Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}" 
                              Visibility="{Binding IsEnabled, Converter={StaticResource BooleanToVisibilityConverter}, RelativeSource={RelativeSource Mode=Self}}"
                              AutomationProperties.Name="Back"
                              AutomationProperties.AutomationId="BackButton"
                              AutomationProperties.ItemType="Navigation Button"/>
                    </StackPanel>
                    <TextBlock x:Name="pageTitle" Text="{StaticResource AppName}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1" 
                       IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Top"/>
                </Grid>
            </Hub.Header>

We can see from the source code that the Hub Header is defined as above.

The content for each of the sections is defined under the HubSection tags.

We will now add a HubSection before the first HubSection in the default generated code.

<HubSection Header="My Section" IsHeaderInteractive="False"  
                Background="#222222" MinWidth="250">
                <DataTemplate>
                    <StackPanel>
                        <TextBlock Text="My section stuff goes here."
                           Style="{ThemeResource BodyTextBlockStyle}" />
                        
                    </StackPanel>
                </DataTemplate>
            </HubSection>

You can now see that the content we added will appear as under.

Windows8._1HubControlDemo
Windows8._1HubControlDemo

We can see how simple it is to add content to the Hub control.

If you have trouble following along, you can download the sample code from below.

 

Summary

In this article, we learned about the new Hub control in Windows 8.1. I hope you have found this information useful.

About the Author

Vipul Patel is a Program Manager currently working at Amazon Corporation. He has formerly worked at Microsoft in the Lync team and in the .NET team (in the Base Class libraries and the Debugging and Profiling team). He can be reached at vipul.patel@hotmail.com



Related Articles

Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Today's agile organizations pose operations teams with a tremendous challenge: to deploy new releases to production immediately after development and testing is completed. To ensure that applications are deployed successfully, an automatic and transparent process is required. We refer to this process as Zero Touch Deployment™. This white paper reviews two approaches to Zero Touch Deployment--a script-based solution and a release automation platform. The article discusses how each can solve the key …

  • On-demand Event Event Date: December 18, 2014 The Internet of Things (IoT) incorporates physical devices into business processes using predictive analytics. While it relies heavily on existing Internet technologies, it differs by including physical devices, specialized protocols, physical analytics, and a unique partner network. To capture the real business value of IoT, the industry must move beyond customized projects to general patterns and platforms. Check out this webcast and join industry experts as …

Most Popular Programming Stories

More for Developers

RSS Feeds