Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Mobile / WinMobile

Design Metro App using windows 8 and Visual studio 2011

4.56/5 (5 votes)
1 May 2012CPOL3 min read 57K   1.8K  
Design Metro App using windows 8 and Visual studio 2011

Introduction

This article is meant for .net developer who are using windows 8 and Visual studio 2011 for developing metro style app. In this article ,I will explain brief information about the metro app and demonstrate the Sample metro app design. 

What is Metro Apps  

Metro style apps are full screen apps tailored to your users' needs, tailored to the device they run on, tailored for touch interaction, and tailored to the Windows user interface. Windows helps you interact with your users, and your users interact with your app." from MSDN.

All about developing for Windows 8: http://www.buildwindows.com/

When developing Metro apps you can chose from a variety of languages and technologies:

  • HTML + JS + CSS 
  • XAML + (C# or VB)
  • XAML + (C++ or C)  

Prerequisites

About My Sample FaceBook PhotoAlbum Metro App 

  • This Sample Metro app have three screens ,first one 'Facebook Login' screen and next 'Album' screen and last one is 'Photo' screen 
  • As i like  XMAL and C# hence i am developing this sample metro application in XMAL and C# . 
  • I am using the FaceBook C# SDK to get albums and photos from FaceBook.   

Step 1   :Create Project  

With the new VS 2011 Developer tool, you will be able to create Windows Metro Style App in C# ,XMAL , Javacsript ,VB . Here i am using C# Grid Template for designing sample FaceBook Photo Album metro style app.

Image 1

Step 2   Add Client Internet Capabilities

 As My Metro App fetch the data from FaceBook hence App need's client internet connection to fetch data from facebook.

To enable to internet capabilities in metro app , double click on Package.appxmanifest file and under the Capabilities tab ,mark internet(client) as checked.  

Image 2 


Step 3:  Add login page  

This page is used to display facebook login dialogue box and authenticate the face book user. 

Image 3 

 LoginPage.xaml page have Login() method  which is used to display the Facebook login dialogue box ,authenticate the Facebook user  and fetch the albums ,photos from Facebook. 

 Below code display the FaceBook Login box

C++
//Facebook AppId
                string faceBookAppId = "285516851528865";
                //Facebook Extended Permissions
                string[] extendedPermissions = new[] { "user_about_me", "offline_access", "user_photos", "publish_stream", "friends_photos" };
                string redirectUri = "https://www.facebook.com/connect/login_success.html";
                System.Uri EndUri = new Uri(redirectUri);
                var oauth = new FacebookClient { AppId = faceBookAppId };
                var parameters = new Dictionary<string, object>
                        {
                            {"client_id",faceBookAppId},
                            { "response_type", "token" },
                            { "display", "popup" },
                            {"redirect_uri",redirectUri}
                        };

                if (extendedPermissions != null && extendedPermissions.Length > 0)
                {
                    var scope = new StringBuilder();
                    scope.Append(string.Join(",", extendedPermissions));
                    parameters["scope"] = scope.ToString();
                }

                Uri loginUrl = oauth.GetLoginUrl(parameters);
                //Show facebook login Dialogue box
                WebAuthenticationResult WebAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(
                                                         WebAuthenticationOptions.None,
                                                         loginUrl, EndUri
                                                         );
Below code shows that once FaceBook authentication is successful ,it will navigate to Album screen (GroupedItemsPage.xaml)
C++
//Show Albums if Facebook login successfull
if (WebAuthenticationResult.ResponseStatus == WebAuthenticationStatus.Success)
{
    FacebookOAuthResult fbAuthResult = oauth.ParseOAuthCallbackUrl(new Uri(WebAuthenticationResult.ResponseData.ToString()));
    var fbClient = new FacebookClient(fbAuthResult.AccessToken);
    //Get Facebook Albums
    dynamic fbAlbums = await fbClient.GetTaskAsync("/me/albums");
    DataSource dataSource = new DataSource();
    foreach (var a in fbAlbums.data)
    {
        //Get Facebook Photos
       var fbPhotos = await fbClient.GetTaskAsync(a.id + "/photos");
       string albumPath="";
       foreach (var p in fbPhotos.data)
       {
           albumPath = p.source;
           break;
       }

       var album = new Album(a.name, albumPath);
       foreach (var p in fbPhotos.data)
           album.Photos.Add(new Photo("", p.source, album));

       dataSource.Albums.Add(album);
    }

    Frame.Navigate(typeof(GroupedphotosPage), dataSource.Albums);

Step4 : Customize the GroupedItemsPage.xaml and ItemDetailPage.xaml file to display Albums and Photos 

  • GroupedItemsPage.xaml page is used to display Facebook user Albums.
  • ItemDetailPage.xaml page is used to display Facebook user album photos.
GroupedItemsPage.xaml  

Preview of Album screen  

Image 4

 

When 'GroupEdItemPage' page loads store the passed data into DataViewModel["Albums"] , we will use this value in design page to display the User Album's 

C#
/// <summary>
       /// Invoked when this page is about to be displayed in a Frame.
       /// </summary>
       /// <param name="e">Event data that describes how this page was reached.  The Parameter
       /// property provides the grouped collection of photos to be displayed.</param>
       protected override void OnNavigatedTo(NavigationEventArgs e)
       {
           this.DefaultViewModel["Albums"] = e.Parameter;
       } 

Creating the UserControl ResourcesResources for Album collection , we will use this resource in GridView to display the Albums.  

C++
<UserControl.Resources>

       <!-- Collection of grouped photos displayed by this page -->
       <CollectionViewSource
           x:Name="groupedphotosViewSource"
           Source="{Binding Albums}"
           IsSourceGrouped="False"
           ItemsPath="Photos"
           d:Source="{Binding Albums, Source={d:DesignInstance Type=data:DataSource, IsDesignTimeCreatable=True}}"/>
   </UserControl.Resources> 

Displaying the Albums in Gridview   

C++
<GridView
                x:Name="itemGridView"
                AutomationProperties.AutomationId="ItemGridView"
                AutomationProperties.Name="Face Book Photo Album"
                Margin="116,0,40,46"
                ItemsSource="{Binding Source={StaticResource groupedphotosViewSource}}"
                ItemTemplate="{StaticResource Standard250x250ItemTemplate}"
                SelectionMode="None"
                IsItemClickEnabled="True"
                ItemClick="ItemView_ItemClick">
                
                  <GridView.ItemsPanel>
                    <ItemsPanelTemplate>                        
                        <VirtualizingStackPanel Orientation="Horizontal"/>
                    </ItemsPanelTemplate>
                </GridView.ItemsPanel>
                <GridView.GroupStyle>
                    <GroupStyle>

                        <GroupStyle.Panel>
                            <ItemsPanelTemplate>
                                <VariableSizedWrapGrid Orientation="Vertical" Margin="0,0,80,0"/>
                            </ItemsPanelTemplate>
                        </GroupStyle.Panel>
                    </GroupStyle>
                </GridView.GroupStyle>
            </GridView>

When user click on Album , following method invoked which navigates to Photo screen.

C#
/// <summary>
        /// Invoked when an item within a group is clicked.
        /// </summary>
        /// <param name="sender">The GridView (or ListView when the application is snapped)
        /// displaying the item clicked.</param>
        /// <param name="e">Event data that describes the item clicked.</param>
        void ItemView_ItemClick(object sender, ItemClickEventArgs e)
        {
            // Navigate to the appropriate destination page, configuring the new page
            // by passing required information as a navigation parameter
            
            this.Frame.Navigate(typeof(ItemDetailPage), e.ClickedItem);
        }  

ItemDetailPage.xaml 

 Preview of photo screen

Image 5 

When 'ItemDetailPage' page loads store the  Selected Album and Photos object into the DefaultViewModel , we will use these object to display the photos on screen 

C#
/// <summary>
       /// Invoked when this page is about to be displayed in a Frame.
       /// </summary>
       /// <param name="e">Event data that describes how this page was reached.  The Parameter
       /// property provides the initial item to be displayed.</param>
       protected override void OnNavigatedTo(NavigationEventArgs e)
       {
           var album = (Album)e.Parameter;
           this.DefaultViewModel["Album"] = album;
           this.DefaultViewModel["Photos"] = album.Photos ;
           //this.flipView.SelectedItem = item;

Creating static resource for photo, we will use this resource in FilpView to display the Photos 

C#
<UserControl.Resources>

        <!-- Collection of items displayed by this page -->
        <CollectionViewSource
            x:Name="itemsViewSource"
            Source="{Binding Photos}"
            d:Source="{Binding Album[0].Photos, Source={d:DesignInstance Type=data:DataSource, IsDesignTimeCreatable=True}}"/>
    </UserControl.Resources>

Displaying the Photos in FilpView 

C#
<FlipView
           x:Name="flipView"
           AutomationProperties.AutomationId="ItemsFlipView"
           AutomationProperties.Name="Item Details"
           Grid.Row="1"
           Margin="0,-3,0,0"
           ItemsSource="{Binding Source={StaticResource itemsViewSource}}">

           <FlipView.ItemTemplate>
               <DataTemplate>

                   <!--
                       UserControl chosen as the templated item because it supports visual state management
                       Loaded/unloaded events explicitly subscribe to view state updates from the page
                   -->
                   <UserControl Loaded="StartLayoutUpdates" Unloaded="StopLayoutUpdates">
                       <ScrollViewer x:Name="scrollViewer" Style="{StaticResource HorizontalScrollViewerStyle}" Grid.Row="1">

                           <!-- Content is allowed to flow across as many columns as needed -->
                           <common:RichTextColumns x:Name="richTextColumns" Margin="117,0,117,47">
                               <RichTextBlock x:Name="richTextBlock" Width="560" Style="{StaticResource ItemRichTextStyle}">

                                   <Paragraph LineStackingStrategy="MaxHeight">
                                       <InlineUIContainer>
                                           <Image x:Name="image" MaxHeight="480" Margin="0,20,0,10" Stretch="Uniform" Source="{Binding Image}"/>
                                       </InlineUIContainer>
                                   </Paragraph>

                               </RichTextBlock>

                               <!-- Additional columns are created from this template -->
                               <common:RichTextColumns.ColumnTemplate>
                                   <DataTemplate>
                                       <RichTextBlockOverflow Width="560" Margin="80,0,0,0">
                                           <RichTextBlockOverflow.RenderTransform>
                                               <TranslateTransform X="-1" Y="4"/>
                                           </RichTextBlockOverflow.RenderTransform>
                                       </RichTextBlockOverflow>
                                   </DataTemplate>
                               </common:RichTextColumns.ColumnTemplate>
                           </common:RichTextColumns>

                           <VisualStateManager.VisualStateGroups>

                               <!-- Visual states reflect the application's view state inside the FlipView -->
                               <VisualStateGroup>
                                   <VisualState x:Name="FullScreenLandscape"/>
                                   <VisualState x:Name="Filled"/>

                                   <!-- Respect the narrower 100-pixel margin convention for portrait -->
                                   <VisualState x:Name="FullScreenPortrait">
                                       <Storyboard>
                                           <ObjectAnimationUsingKeyFrames Storyboard.TargetName="richTextColumns" Storyboard.TargetProperty="Margin">
                                               <DiscreteObjectKeyFrame KeyTime="0" Value="97,0,87,57"/>
                                           </ObjectAnimationUsingKeyFrames>
                                           <ObjectAnimationUsingKeyFrames Storyboard.TargetName="image" Storyboard.TargetProperty="MaxHeight">
                                               <DiscreteObjectKeyFrame KeyTime="0" Value="400"/>
                                           </ObjectAnimationUsingKeyFrames>
                                       </Storyboard>
                                   </VisualState>

                                   <!-- When snapped, the content is reformatted and scrolls vertically -->
                                   <VisualState x:Name="Snapped">
                                       <Storyboard>
                                           <ObjectAnimationUsingKeyFrames Storyboard.TargetName="richTextColumns" Storyboard.TargetProperty="Margin">
                                               <DiscreteObjectKeyFrame KeyTime="0" Value="17,0,17,57"/>
                                           </ObjectAnimationUsingKeyFrames>
                                           <ObjectAnimationUsingKeyFrames Storyboard.TargetName="scrollViewer" Storyboard.TargetProperty="Style">
                                               <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource VerticalScrollViewerStyle}"/>
                                           </ObjectAnimationUsingKeyFrames>
                                           <ObjectAnimationUsingKeyFrames Storyboard.TargetName="richTextBlock" Storyboard.TargetProperty="Width">
                                               <DiscreteObjectKeyFrame KeyTime="0" Value="280"/>
                                           </ObjectAnimationUsingKeyFrames>
                                           <ObjectAnimationUsingKeyFrames Storyboard.TargetName="image" Storyboard.TargetProperty="MaxHeight">
                                               <DiscreteObjectKeyFrame KeyTime="0" Value="160"/>
                                           </ObjectAnimationUsingKeyFrames>
                                       </Storyboard>
                                   </VisualState>
                               </VisualStateGroup>
                           </VisualStateManager.VisualStateGroups>
                       </ScrollViewer>
                   </UserControl>
               </DataTemplate>
           </FlipView.ItemTemplate>
       </FlipView> 

Step5: Set LoginPage.xmal page as startup page 

Open the App.xmal.cs and set the LoginPage As startup paage,  as shown below  

C++
protected override void OnLaunched(LaunchActivatedEventArgs args)
      {
          // TODO: Create a data model appropriate for your problem domain to replace the sample data
          var sampleData = new DataSource();

          if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
          {
              //TODO: Load state from previously suspended application
          }

          // Create a Frame to act navigation context and navigate to the first page,
          // configuring the new page by passing required information as a navigation
          // parameter
          var rootFrame = new Frame();
          rootFrame.Navigate(typeof(LoginPage));

          // Place the frame in the current Window and ensure that it is active
          Window.Current.Content = rootFrame;
          Window.Current.Activate();
      } 

Attached Code  

SampleFaceBookPhoto.zip contain the all the my SampleFacebookPhotoalbumm Metro App files.

History

Keep a running update of any changes or improvements you've made here.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)