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

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read