创建 Windows8 应用Part 1: "Hello, world"

这个教程将讲授如何使用 C# 语言和 Xaml 创建简单的 “Hello, World”Windows 8 应用。这是讲授如何创建 Windows8 应用系列的第一部分。

在这个教程中,你讲学会如何:

  • 创建新的项目
  • 在开始页中添加 Xaml 内容
  • 处理触摸,笔,以及鼠标输入
  • 切换 Ligth 和 Dark 主题
  • 创建自定义的样式

我们将演示如何使用 C# 和 XAML 创建 Windows 商店应用。

开始之前...

  • 为了完成这个教程,你需要Windows 8 和 Microsoft Visual Studio Express 2012 for Windows 8. 下载它们, 参阅​​Get the tools​​.
  • 你还需要一个开发者授权. 获取的说明, 参阅​​Get a developer license​​.
  • 我们假定你已经基本理解XAML 以及在​​XAML overview​​ 中提及的概念.
  • 我们假定你使用默认的Microsoft Visual Studio 布局。如果你改变了默认的布局,你可以在Window菜单中,点击Reset Window Layout来重新复位.
  • 你可以在这里查阅完整的代码​​Part 1 complete code​​.

Step 1: 在Visual Studio 中创建新项目

  1. 启动 Visual Studio Express 2012 for Windows 8.

见到 Visual Studio 的启动屏幕。

(在后面的内容中, 我们使用 “Visual Studio”代表Visual Studio Express 2012 for Windows 8.)

  1. 选择File>New Project.

New Project 新建项目对话框出现。对话框的左边栏允许你选择模版的类型.


3. 在左边栏中,展开Installed > Templates, 然后展开Visual C# 并且选中Windows Store 模版类型. 对话框中间的区域将会显示关于 Windows Store 应用的一个模版列表。


 

  1. 在中间区域, 选择Blank App模版.

Blank App 模版创建一个最小规模的可以编译和运行的 Windows Store 应用程序,但是并不包含任何的用户交互和数据处理。贯穿这个教程中,你将添加控件和数据到应用程序中。

  1. Name输入框中, 输入 "HelloWorld".
  2. 点击OK创建项目

Visual Studio 将会创建项目,然后在解决方案管理器Solution Explorer 中显示项目。

 

尽管 Blank App 是最小规模的模版, 它仍然包含了许多文件:

  • 一个描述应用的清单文件 manifest file (package.appxmanifest),包括 (应用的名字,介绍,标题,开始页等等),以及应用包含文件的列表。
  • 一套显示在开始屏幕上的大的,小的logo 图标 (logo.png 和smalllogo.png)。
  • 在 Windows Store 中展示应用的图片(storelogo.png)
  • 在应用启动的时候显示的闪屏图片 (splashscreen.png)
  • 应用的XAML 和代码文件(App.xaml and App.xaml.cs) .
  • 在启动应用的时候显示的开始页面 (MainPage.xaml) 和相关的后台代码文件 (MainPage.xaml.cs/.vb)

这些文件是使用 C# 开发 Windows Store 应用的基本文件。任何在 Visual Studio 中创建的 Windows Store 项目都包含这些文件。

替换 MainPage 页面

Blank App 项目模版中包含的 MainPage 基于Blank Page 页面模版创建,它包含最小化的 XAML 和代码来创建 Page 实例。可是,当创建 Windows Store 应用的时候,你需要做更多工作,举例来说,即使一个单页的应用, 也需要处理不同的布局和视图,在暂停的时候保存应用的状态, 在应用恢复的时候恢复状态。在 Visual Studio 中其它的项目和 Page 模版中,包含额外的代码和助手类来帮助你进行视图和状态的管理。在你使用Blank App 项目模版的时候,一般来说,你会使用其他的页面模版来替换掉空白的 MainPage 页面。来获取布局和助手类带来的好处。

在这个例子中,我们将使用 Basic Page 模版替换默认的 MainPage。在教程的后面我们将会使用新模版带来的视图和状态管理。关于在 Visual Studio 中可以使用的更多地页面模版,可以查阅​​C#, VB, and C++ item templates​​.

在项目中替换MainPage 页面

  1. 在解决方案管理器Solution Explorer 中, 右键点击MainPage.xaml ,然后选择删除Delete.
  2. 点击OK确认删除。
  3. 选择Project>Add New Item. 打开添加新项目Add New Item对话框. 类似新建项目对话框.
  4. 在左边栏的Visual C#中, 选择Windows Store模版类型
  5. 在中间栏中, 选择Basic Page作为加入到项目中的页面类型
  6. 输入 "MainPage.xaml" 作为页面名称

重要:如果保留默认的名称 "BasicPage1", 项目将不能正确创建。.

  1. 点击Add.

在第一次在应用中添加基于Blank App 模版的页面的时候(不是Blank Page), Visual Studio 将会显示一个对话框,提示你的项目缺少一些依赖的文件,点击 Yes 添加这些文件. 包含实用工具的这些文件将被加入到项目的Common 文件夹中。

页面的XAML 和后台代码文件将被加入到项目中。

  1. 点击Build>Build solution创建应用

重要:除非你编译依赖的助手类,否则在 Visual Studio 中新的页面将会在设计器中显示一个错误信息。

Step 2: 启动应用

到这一步,你已经创建了一个非常简单的应用。如果你希望看到应用的样子,按 F5 在调试模式中编译,发布,运行应用。默认的闪屏首先出现,闪屏使用一个图片 (splashscreen.png) 和背景颜色( 在 app 的清单文件中指定). 我们没有涵盖这一部分,但是很容易定制你的闪屏界面。(要知道如何完成, 查阅​​Adding a splash screen​​.)

闪屏出现,然后应用出现,包含标题为 “My Application”的黑色屏幕。

 

没有按钮或者命令来关闭应用。你可以使用关闭的手势或者 Alt+F4 来关闭它。但是一般我们不会关闭应用,我们将在第二部分​​Part 2: 管理应用的生命周期和状态​​ 中进行讨论。按 Windows 键导航到开始屏幕,注意应用发布后,应用的磁贴被追加到开始屏幕的最后一个组中。再次运行这个应用,触摸或者点击开始屏幕上的磁贴就可以了,或者还是在Visual Studio 中按 F5 在调试模式运行。

看起来不多,但还是要祝贺你一下,你已经完成了你的第一个Windows Store 应用!

停止调试应用, 按  Alt+Tab 从应用返回Visual Studio. 在 Visual Studio, 点击 Debug > Stop debugging 关闭应用. 在调试的时候,你不能修改应用。

更多信息, 参阅 ​​Running Windows Windows Store apps from Visual Studio​​.

Step 3: 修改开始页面

文件中有什么?

在使用Blank App 项目模版创建新的项目之后,Visual Studio 创建了一个包含少数几个文件的应用. 查看或者编辑这些文件, 在解决方案管理其中双击这些文件就可以,你可以像展开文件夹一样展开 XAML 文件来查看相关的代码文件。XAML 文件在打开的时候,会在一个拆分窗口中分别显示设计界面和XAML 编辑器。

在这个教程中,你只需要树立前面列出的很少几个文件: App.xaml, App.xaml.cs, MainPage.xaml, and MainPage.xaml.cs。

App.xaml

App.xaml 是你定义整个应用使用的资源的地方。这个文件包含一个关联到位于Common 文件夹中的StandardStyles.xaml 文件的 ​ResourceDictionary​ . StandardStyles.xaml 提供了一套为你的应用提供 Windows 8 观感的默认样式。

<Application
x:Class="HelloWorld.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:HelloWorld">

<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>

<!--
Styles that define common aspects of the platform look and feel
Required by Visual Studio project and item templates
-->
<ResourceDictionary Source="Common/StandardStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>

</ResourceDictionary>
</Application.Resources>
</Application>

App.xaml.cs

App.xaml.cs 是App.xaml 的后台代码文件. 后台代码是连接到 XAML 页面的部分类代码。 XAML 和后台代码一起构成完整的类定义。App.xaml.cs 是应用的入口点. 类似于所有的后台代码页面,它包含一个构造函数,其中调用了初始化方法​​InitializeComponent。你不需要写初始化方法InitializeComponent​​​. 它由Visual Studio 自动生成, 主要功能是初始化定义在XAML 文件中的元素。App.xaml.cs 也包含了激活和暂停应用的处理方法,在本教程的第二部分​​Part 2: Manage app lifecycle and state​​将在这些方法中增加代码处理

using System;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227

namespace HelloWorld
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App : Application
{
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
}

/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used when the application is launched to open a specific file, to display
/// search results, and so forth.
/// </summary>
/// <param name="args">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
Frame rootFrame = Window.Current.Content as Frame;

// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();

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

// Place the frame in the current Window
Window.Current.Content = rootFrame;
}

if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
if (!rootFrame.Navigate(typeof(MainPage), args.Arguments))
{
throw new Exception("Failed to create initial page");
}
}
// Ensure the current window is active
Window.Current.Activate();
}

/// <summary>
/// Invoked when application execution is being suspended. Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
}
}


MainPage.xaml

在 MainPage.xaml 中定义应用的 UI . 可以直接使用 XAML 增加元素,或者使用 Visual Studio 提供的设计工具也可以。 Basic Page 模版创建了一个名为 MainPage 的派生自​​LayoutAwarePage ​​​新的类(或者你在创建页面的时候命名的类). ​​LayoutAwarePage​​​ 扩展了基类 ​Page​ 提供了关于导航,状态管理,以及视图管理的方法. Basic Page 模版中也包含了一些简单的内容,像一个返回按钮和一个标题.

<common:LayoutAwarePage
x:Name="pageRoot"
x:Class="HelloWorld.MainPage"
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
IsTabStop="false"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:HelloWorld"
xmlns:common="using:HelloWorld.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Page.Resources>

<!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
<x:String x:Key="AppName">My Application</x:String>
</Page.Resources>

<!--
This grid acts as a root panel for the page that defines two rows:
* Row 0 contains the back button and page title
* Row 1 contains the rest of the page layout
-->
<Grid Style="{StaticResource LayoutRootStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

<!-- Back button and page title -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="backButton" Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" Style="{StaticResource BackButtonStyle}"/>
<TextBlock x:Name="pageTitle" Grid.Column="1" Text="{StaticResource AppName}" Style="{StaticResource PageHeaderTextStyle}"/>
</Grid>

<VisualStateManager.VisualStateGroups>

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

<!-- The entire page respects the narrower 100-pixel margin convention for portrait -->
<VisualState x:Name="FullScreenPortrait">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PortraitBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>

<!-- The back button and title have different styles when snapped -->
<VisualState x:Name="Snapped">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedPageHeaderTextStyle}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</common:LayoutAwarePage>


MainPage.xaml.cs

MainPage.xaml.cs 是MainPage.xaml 的后台代码. 在这里你可以添加应用的逻辑和事件处理. Basic Page 模版包含两个用来保存和加载页面状态的代码.

using System;
using System.Collections.Generic;
using Windows.UI.Xaml.Controls;

// The Basic Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234237

namespace HelloWorld
{
/// <summary>
/// A basic page that provides characteristics common to most applications.
/// </summary>
public sealed partial class MainPage : HelloWorld.Common.LayoutAwarePage
{
public MainPage()
{
this.InitializeComponent();
}

/// <summary>
/// Populates the page with content passed during navigation. Any saved state is also
/// provided when recreating a page from a prior session.
/// </summary>
/// <param name="navigationParameter">The parameter value passed to
/// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested.
/// </param>
/// <param name="pageState">A dictionary of state preserved by this page during an earlier
/// session. This will be null the first time a page is visited.</param>
protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
}

/// <summary>
/// Preserves state associated with this page in case the application is suspended or the
/// page is discarded from the navigation cache. Values must conform to the serialization
/// requirements of <see cref="SuspensionManager.SessionState"/>.
/// </summary>
/// <param name="pageState">An empty dictionary to be populated with serializable state.</param>
protected override void SaveState(Dictionary<String, Object> pageState)
{
}
}
}

修改开始页面

现在, 让我们为应用增加一些内容.

修改开始页面

  1. 在解决方案管理器中双击 MainPage.xaml 打开它。.
  2. 改变页面的标题,在 XAML 设计器中,选中在页面开始部分的 "My Application" 文本

在属性窗口中,确认 ​TextBlock​​ 命名为 ​​pageTitle。默认情况下,属性窗口​Properties 在解决方案管理Solution Explorer 下面。

  1. 属性窗口Properties包含选中元素的一系列属性和值的列表. 每个属性值得后面有一个属性编辑器property marker, 一个小盒子的符号表示点击之后会出现一个属性的菜单。Text 属性编辑器为绿色表示它通过资源设置。
  2. 在属性菜单中选择Edit Resource. 编辑资源Edit Resource对话框弹出.
  3. 在编辑资源对话框Edit Resource中, 将"My Application" 替换为 "Hello, world!".
  4. 点击OK.

不是在文本块中直接输入应用的名字,你现在通过字符串资源更新了 Text 属性绑定的值。使用这种方式使得文本可以被重用。易于维护,更容易被本地化。

<x:String x:Key="AppName">Hello, world!</x:String>
  1. 在 XAML 编辑器中, 添加UI 控件.

在根元素 ​Grid​​, 紧跟着 ​​<VisualStateManager.VisualStateGroups>​​​ 标记, 增加后面的 XAML. 包含一个堆栈布局 ​StackPanel​​ ,带有一个提示用户名称的文本块 ​TextBlock​​,一个接收用户输入名字的​TextBox​ ,一个按钮,和另外一个TextBlock 元素。

<StackPanel Grid.Row="1" Margin="120,30,0,0">
<TextBlock Text="What's your name?"/>
<StackPanel Orientation="Horizontal" Margin="0,20,0,20">
<TextBox x:Name="nameInput" Width="300" HorizontalAlignment="Left"/>
<Button Content="Say "Hello""/>
</StackPanel>
<TextBlock x:Name="greetingOutput"/>
</StackPanel>

在 ​​Part 3: Navigation, layout, and views​​.中,我们将会讨论布局问题。

  1. 按 F5 运行. 如下所示。

你可以在输入框中输入,现在,点击按钮不会有任何反应。在下一步,我们将会创建一个事件处理程序来处理按钮的点击事件,显示一个个性化的问候,