65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Windows 8 和 Visual Studio 2011 设计 Metro 应用

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.56/5 (5投票s)

2012 年 5 月 1 日

CPOL

3分钟阅读

viewsIcon

57660

downloadIcon

1803

使用 Windows 8 和 Visual Studio 2011 设计 Metro 应用

引言

本文档面向使用 Windows 8 和 Visual Studio 2011 开发 Metro 风格应用.NET 开发者。在本文中,我将简要介绍 Metro 应用,并演示一个示例 Metro 应用设计。

什么是 Metro 应用?

Metro 风格的应用是全屏应用,针对用户的需求、运行设备、触摸交互以及 Windows 用户界面进行了优化。Windows 帮助您与用户互动,您的用户与您的应用互动。”摘自 MSDN:MSDN

关于 Windows 8 开发:http://www.buildwindows.com/

开发 Metro 应用时,您可以选择多种语言和技术。

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

必备组件

关于我的示例 Facebook 照片相册 Metro 应用

  • 此示例 Metro 应用有三个屏幕:第一个是“Facebook 登录”屏幕,接着是“相册”屏幕,最后一个是“照片”屏幕。
  • 由于我喜欢 XAML 和 C#,因此我使用 XAML 和 C# 开发了这个示例 Metro 应用。
  • 我正在使用 Facebook C# SDK 从 Facebook 获取相册和照片。

步骤 1:创建项目 

借助新的 VS 2011 开发工具,您将能够使用 C#、XAML、JavaScript、VB 创建 Windows Metro 风格的应用。在此,我将使用 C# 网格模板来设计示例 Facebook 照片相册 Metro 风格的应用。

步骤 2:添加客户端 Internet 功能

由于我的 Metro 应用从 Facebook 获取数据,因此应用需要客户端 Internet 连接才能从 Facebook 获取数据。

要在 Metro 应用中启用 Internet 功能,请双击 Package.appxmanifest 文件,然后在“功能”选项卡下,将“Internet (客户端)”标记为选中状态。

 


步骤 3:添加登录页面

此页面用于显示 Facebook 登录对话框并验证 Facebook 用户。

 

LoginPage.xaml 页面包含 Login() 方法,该方法用于显示 Facebook 登录对话框、验证 Facebook 用户以及从 Facebook 获取相册和照片。

以下代码显示了 Facebook 登录框:

//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://#/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
                                                         );
以下代码显示,一旦 Facebook 身份验证成功,它将导航到“相册”屏幕 (GroupedItemsPage.xaml):
                //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);

步骤 4:自定义 GroupedItemsPage.xaml 和 ItemDetailPage.xaml 文件以显示相册和照片 

  • GroupedItemsPage.xaml 页面用于显示 Facebook 用户相册。
  • ItemDetailPage.xaml 页面用于显示 Facebook 用户相册照片。
GroupedItemsPage.xaml  

相册屏幕预览

 

当 GroupedItemPage 页面加载时,将传入的数据存储到 DataViewModel["Albums"] 中,我们将在设计页面中使用此值来显示用户相册。

 /// <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;
        } 

创建相册集合的用户控件资源,我们将在 GridView 中使用此资源来显示相册。

 <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> 

在 Gridview 中显示相册

<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>

当用户单击相册时,将调用以下方法,该方法导航到照片屏幕。

/// <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 

照片屏幕预览

 

当 ItemDetailPage 页面加载时,将选定的相册和照片对象存储到 DefaultViewModel 中,我们将使用这些对象在屏幕上显示照片。

 /// <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;
        } 

创建照片的静态资源,我们将在 FlipView 中使用此资源来显示照片。

<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>

在 FlipView 中显示照片

 <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> 

步骤 5:将 LoginPage.xaml 页面设置为启动页

打开 App.xaml.cs 并将 LoginPage 设置为启动页,如下图所示:

  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();
        } 

附加代码

SampleFaceBookPhoto.zip 包含我所有的 SampleFacebookPhotoalbumm Metro 应用文件。

历史

在此处保持您所做的任何更改或改进的实时更新。
© . All rights reserved.