.NET Zone is brought to you in partnership with:

Den is a DZone Zone Leader and has posted 460 posts at DZone. You can read more from them at their website. View Full User Profile

Porting Visual Studio Achievements for WP to Windows 8 - Getting primary user input

03.12.2012
| 3007 views |
  • submit to reddit

If you missed the previous two articles in the series:

Since the basic infrastructure is working, it is time to make sure that the end-user actually can customize the experience by adding users he wants to track instead of using the sample (stock) option. In the Windows Phone project, I had a page called InputPage.xaml. The name itself is a bit ambiguous, because it is only used to add users, so in my Metro project I decided to name it AddUserPage.xaml:

Once created, I dumped the existing sample StackPanel in the blank layout. I removed phone-based references (e.g. specific styles) as well as redundant events for now - I will add those later. I ended up with this XAML snippet:

    <Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
        <StackPanel Margin="20,20,20,90">
            <Grid Margin="0,0,0,10" Width="440">
                <Image HorizontalAlignment="Left" Source="Images/adduser.png"></Image>
            </Grid>

            <TextBlock Foreground="White" Margin="15,10,15,0" TextWrapping="Wrap" Text="enter channel9 user name" FontSize="30"></TextBlock>
            <TextBox x:Name="txtUsername" BorderBrush="Black" Foreground="Black" Margin="0,10,0,0"></TextBox>
        </StackPanel>
    </Grid>

NOTE: I am well-aware that at this point I am not paying much attention to the UI. Instead, I decided to focus on functionality first. The "prettyfying" process will be documented later.

Getting back to MainPage.xaml, I need to somehow invoke the user addition page. To do this, I need to have an application bar with an "add" button. The process is very similar to the one on Windows Phone. Just take a look at this XAML:

<AppBar x:Name="BottomAppBar"  Height="88" VerticalAlignment="Bottom">
    <StackPanel Orientation="Horizontal">
        <StackPanel Orientation="Vertical" Margin="5,14,5,14">
            <Button Content="Add" x:Name="btnAddUser" Click="btnAddUser_Click"></Button>
        </StackPanel>
    </StackPanel>
</AppBar>

It becomes a little bit tricky when it comes to page navigation. In Windows 8, the concept of direct page-to-page navigation is structured a bit different. The developer has to manually create a root frame, that will handle page navigation. That being said, go to MainPage.xaml and cut the entire content grid, leaving LayoutRoot alone. Create a new blank page and name it HomeView.xaml. Paste the contents you just cut in HomeView.

That will be the starting page for your application, and it will be a part of the root frame that I am going to create.

NOTE: If you are a beginner in Windows 8 Metro app navigation, I recommend starting with this read.

In MainPage.xaml, the Frame declaration looks like this (exactly like it was shown in the sample):

<Frame x:Name="RootFrame">
    <Frame.ContentTransitions>
        <TransitionCollection>
            <EntranceThemeTransition FromHorizontalOffset="200"></EntranceThemeTransition>
        </TransitionCollection>
    </Frame.ContentTransitions>
</Frame>

In the code-behind, I added one line so that when MainPage is loaded, I will see HomeView - the view that shows the list of tracked Channel9 users. Something like this should do the trick:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    RootFrame.Navigate(typeof(HomeView));
}

The navigation harness is now in place, so I can now easily add the input navigation fragment. Going to HomeView, I am editing the btnAddUser_Click event handler to do this:

Frame.Navigate(typeof(AddUserPage));

In AddUserPage, I am also adding an AppBar element, so that I can use the OK and Cancel buttons.

<AppBar x:Name="BottomAppBar"  Height="88" VerticalAlignment="Bottom">
    <StackPanel Orientation="Horizontal" Margin="5,14,5,14">
        <Button Content="OK" x:Name="btnOK" Click="btnOK_Click"></Button>
        <Button Content="Cancel" x:Name="btnCancel" Click="btnCancel_Click"></Button>
    </StackPanel>
</AppBar>

The event handlers themselves are almost the same as in its Windows Phone counterpart, with the exception of async references - the MessageBox is called via an awaitable ShowAsync method.

async private void btnOK_Click(object sender, RoutedEventArgs e)
{
    if (!Util.CheckIfUserExists(txtUsername.Text))
    {
        NinerReader reader = new NinerReader();
        reader.GetNiner(txtUsername.Text, true, niner =>
        {
            BindingPoint.Instance.Niners.Add(niner);

            if (Frame.CanGoBack)
                Frame.GoBack();
        });
    }
    else
    {
        MessageDialog dialog = new MessageDialog("User already registered.");
        await dialog.ShowAsync();
    }
}

private void btnCancel_Click(object sender, RoutedEventArgs e)
{
    if (Frame.CanGoBack)
        Frame.GoBack();
}

Also, notice how NavigationService was replaced with Frame. In this case, Frame refers to the parent frame that contains the view. The navigation works perfectly between the existing two views, and the user can now add multiple Channel9 members to be tracked.