[翻译]WP7 QuickStart-第十篇-页面导航

 

原文地址:http://create.msdn.com/en-US/education/quickstarts/Navigation

 

【译者注:这篇文章是翻译自微软官方的WP7 QuickStart的第十篇,讲述WP下的页面导航。部分内容加入了自己的理解和表达习惯。而翻译此系列的主要目的一是为了练习英语,二是让自己作为一个 BI开发者对WP7的开发有一个了解。部分翻译不当的地方望各位高人指出批评指正】

 

Windows Phone下的导航可以定义为是允许用户在不同内容的页面之间的来回移动。这种导航模型使你能创建更符合Windows Phone的基于视图的应用程序。此篇主要描述在程序中如何在不同页面之间导航。

 

主要包括以下内容:

框架和页面

页面导航

数据的传递

应用程序栏

后退按钮

 

框架和页面

在Windows Phone下的导航和传统中的Silverlight比较相似,但是它已经被扩展成搭载手机特殊功能的方式。这个导航模型基于PhoneApplicationFrame控件。这个控件包含用户可以导航的一个或者多个PhoneApplicationPage控件。

clip_image001

页面是一个持续状态的集合,它可以视为一个包含内容或者链接到其它页面的链接的Silverlight页面。应用程序中也可以包含弹出页面,消息框,登录页面以及初始屏幕。

只有两个页面之间的移动才被认为是Windows Phone的导航。从登录界面或者初始屏幕移动到主页面是不被认为是导航,而是转移【译者注:Transition】。

 

页面导航

页面导航最简单的方式就是通过HyperlinkButton控件,其中的NavigationUri属性用来指定导航到哪个页面。下面的示例演示如何从一个页面导航到另一个叫SecondPage.xaml的页面。

XAML

<HyperlinkButton NavigateUri="SecondPage.xaml" />

如果不想使用HyperlinkButton,可以使用NavigationService来实现导航。这个类包含一些属性和方法以及事件来帮助你完成导航。其中的NavigationService.Navigate方法用来导航到一个指定的页面。从一个页面导航到另一个页面,遵循下面的步骤。

1. 在Visual Studio里创建一个Windows Phone应用程序。

2. 填加一个Windows Phone纵向页面,名称为SecondPage.xaml,主页面MainPage将导航到这个页面。

3. 使用NavigationService.Navigate方法导航到SecondPage.xaml。

4. 使用NavigationService.GoBack方法返回到MainPage.xaml

下面的示例创建两个页面,名称为Home页和Second页。你可以在Home页面单击“Go to the second page”按钮跳转到Second页面。这就是用到了在按钮的单击事件处理中调用NavigationService.Navigate方法以及Second页面的URL信息实现的。在Second页面中也可以单击“Go back to Main Page”按钮返回到Home页面,这里调用的是NavigationService.GoBack方法。这个方法将后退到最近的一个页面,在这个示例里就是Home页面。在这个方法被调用之前,需要通过NavigationService.CanGoBack属性判定下是否存在回退到的页面。

提示:

尽管这个示例中用到的是NavigationService.GoBack方法,点击设备上的后退按钮一样也是可以导航到前一个页面的。

MainPage.xaml

<Grid x:Name="LayoutRoot" Background="Transparent">

<Grid.RowDefinitions>

<RowDefinition Height="Auto"/>

<RowDefinition Height="*"/>

</Grid.RowDefinitions>

<!--TitlePanel contains the name of the application and page title-->

<StackPanel x:Name="TitlePanel" Grid.Row="0"

Margin="12,17,0,28">

<TextBlock x:Name="ApplicationTitle" Text="Navigation"

Style="{StaticResource PhoneTextNormalStyle}"/>

<TextBlock x:Name="PageTitle" Text="home page"

Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

</StackPanel>

<!--ContentPanel - place additional content here-->

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

<Button x:Name="MyButton" Height="100" Width="350"

Click="MyButton_Click" Content="Go to Second Page"/>

</Grid>

</Grid>

MainPage.xaml.cs

private void MyButton_Click(object sender, RoutedEventArgs e)

{

NavigationService.Navigate(new Uri("/SecondPage.xaml",

UriKind.RelativeOrAbsolute));

}

SecondPage.xaml

<Grid x:Name="LayoutRoot" Background="Transparent">

<Grid.RowDefinitions>

<RowDefinition Height="Auto"/>

<RowDefinition Height="*"/>

</Grid.RowDefinitions>

<!--TitlePanel contains the name of the application and page title-->

<StackPanel x:Name="TitlePanel" Grid.Row="0"

Margin="12,17,0,28">

<TextBlock x:Name="ApplicationTitle" Text="Navigation"

Style="{StaticResource PhoneTextNormalStyle}"/>

<TextBlock x:Name="PageTitle" Text="second page"

Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

</StackPanel>

<!--ContentPanel - place additional content here-->

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

<Button x:Name="BtnBack" Content="Go Back to Home Page"

Click="BtnBack_Click" Height="100" Width="350"/>

</Grid>

</Grid>

SecondPage.xaml.cs

private void BtnBack_Click(object sender, RoutedEventArgs e)

{

if (NavigationService.CanGoBack)

NavigationService.GoBack();

}

下图显示了Home页和Second页的效果。它们之间的导航就是通过NavigationServie.Navigate和NavigationService.GoBack方法实现的。

clip_image002

 

数据的传递

通常,你会希望从一个页面到另一个页面导航的过程中传递一些参数。比如,在Home页中输入一些文本,然后显示在Second页上。这就可以通过NavigationService.Navigate方法,把参数放到被导航页面的后面。也可以重写SecondPage.xaml.cs的Page.OnNavigatedTo方法检查页面的导航请求以及传递的参数。下面具体演示下如何用VavigationService.Navigate和Page.OnNavigatedTo方法在页面之间传递参数。

MainPage.xaml

<Grid x:Name="LayoutRoot" Background="Transparent">

<Grid.RowDefinitions>

<RowDefinition Height="Auto"/>

<RowDefinition Height="*"/>

</Grid.RowDefinitions>

<!--TitlePanel contains the name of the application and page title-->

<StackPanel x:Name="TitlePanel" Grid.Row="0"

Margin="12,17,0,28">

<TextBlock x:Name="ApplicationTitle" Text="Navigation"

Style="{StaticResource PhoneTextNormalStyle}"/>

<TextBlock x:Name="PageTitle" Text="home page"

Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

</StackPanel>

<!--ContentPanel - place additional content here-->

<StackPanel x:Name="ContentPanel" Grid.Row="1"

Margin="12,0,12,0">

<TextBox x:Name="MyTB" Height="80"

Width="350" />

<Button x:Name="MyButton" Content="Go to Second Page"

Height="80" Width="350" Click="MyButton_Click"/>

</StackPanel>

</Grid>

MainPage.xaml.cs

private void MyButton_Click(object sender, RoutedEventArgs e)

{

NavigationService.Navigate(new Uri("/SecondPage.xaml?msg=" +

MyTB.Text, UriKind.RelativeOrAbsolute));

}

SecondPage.xaml

<Grid x:Name="LayoutRoot" Background="Transparent">

<Grid.RowDefinitions>

<RowDefinition Height="Auto"/>

<RowDefinition Height="*"/>

</Grid.RowDefinitions>

<!--TitlePanel contains the name of the application and page title-->

<StackPanel x:Name="TitlePanel" Grid.Row="0"

Margin="12,17,0,28">

<TextBlock x:Name="ApplicationTitle" Text="Navigation"

Style="{StaticResource PhoneTextNormalStyle}"/>

<TextBlock x:Name="PageTitle" Text="second page"

Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

</StackPanel>

<!--ContentPanel - place additional content here-->

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

<TextBlock x:Name="MyTBl" FontSize="25"/>

</Grid>

</Grid>

SecondPage.xaml.cs

protected override void OnNavigatedTo

(System.Windows.Navigation.NavigationEventArgs e)

{

base.OnNavigatedTo(e);

string msg = "";

if (NavigationContext.QueryString.TryGetValue("msg", out msg))

MyTBl.Text = msg;

}

运行的效果如下图,在Home页面输入的文本会显示在Second页面。

clip_image003

 

应用程序栏

应用程序栏是一组单个或者四个的按钮,它们在竖屏模式中显示在屏幕的底端,在横屏模式中显示在屏幕的边缘。这就是Windows Phone 下的菜单系统,在应用程序栏下的按钮为用户提供经常被使用到的一些功能。

下图演示的是Windows Phone 应用程序栏的展开模式。

clip_image004

这些带图标的按钮最多只能有四个,超过四个的话在程序启动的时候会抛异常。在应用程序栏右上角的省略号用来展开或者关闭应用程序栏,图标按钮的文本只有当其展开的时候才会显示出来。可以用Click事件来处理这些图标按钮的单击事件。

在这些按钮的下面,应用程序栏还可以包含一个或多个基于文本的菜单。这些菜单以列表的方式显示,当用户单击应用程序栏右上角的省略号或者图标按钮空白处的时候从屏幕的底部滑入。在上一个图中,About和Settings就是菜单项。菜单项不是横向排列的,所以其不是任何图标按钮的子菜单,相反,这里的菜单项应该是在应用程序中不太被用到的操作或者是那种用图标很难表示的功能必须需要文本描述的操作。

下图是应用程序栏的展开和关闭的模式,以及有菜单项和没有菜单项的形式。

clip_image005

在Windows Phone中可以通过ApplicationBar这个类以编程的方式填加应用程序栏,包括在XAML和代码中。如果以XAML的方式,在Windows Phone开发工具里的Windows Phone项目模版会在MainPage.xaml中包含一个应用程序栏的实现,你需要做的就是取消掉应用程序栏的注释然后根据你的需要去使用你自己的图标和菜单。

下面演示用模版默认创建的修改过后的应用程序栏,其中有三个图标按钮,new,folder和sync以及两个菜单项setting和add email accound。

XAML

<phone:PhoneApplicationPage.ApplicationBar>

<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">

<shell:ApplicationBarIconButton x:Name="newButton"

IconUri="/Images/appbar.new.rest.png" Text="new"

Click="newButton_Click"/>

<shell:ApplicationBarIconButton x:Name="folderButton"

IconUri="/Images/appbar.folder.rest.png" Text="folders"

Click="folderButton_Click"/>

<shell:ApplicationBarIconButton x:Name="syncButton"

IconUri="/Images/appbar.refresh.rest.png" Text="sync"

Click="syncButton_Click"/>

<shell:ApplicationBar.MenuItems>

<shell:ApplicationBarMenuItem Text="settings"/>

<shell:ApplicationBarMenuItem Text="add email account"/>

</shell:ApplicationBar.MenuItems>

</shell:ApplicationBar>

</phone:PhoneApplicationPage.ApplicationBar>

效果如下图:

clip_image006

注意这个示例里用到了图标按钮的图片。关于设计和创建应用程序栏的图片,以及如何定位到准备好的图片,参考这里

应用程序栏不是Silverlight控件所以不支持数据邦定。这也就是说在XAML中的按钮标签必须手动去写并且不能被国际化。如果想实现国际化功能,可以在代码里创建应用程序栏,或者在运行时里用c#去更改标签值。

下面的示例演示如何在代码中创建应用程序栏。首先用ApplicationBar类创建一个应用程序栏,然后通过ApplicationBarIconButton类创建图标按钮并且通过ApplicationBar.Buttons.Add方法加入到应用程序栏中。同时使用ApplicationBarMenuItem创建菜单项并且用ApplicationBar.MenuItems.Add方法填加到应用程序栏中。

C#

public MainPage()

{

InitializeComponent();

//Create the ApplicationBar

ApplicationBar = new ApplicationBar();

ApplicationBar.IsVisible = true;

ApplicationBar.IsMenuEnabled = true;

//Create the icon buttons and setting its properties

ApplicationBarIconButton newButton = new ApplicationBarIconButton(new Uri

("/Images/appbar.add.rest.png", UriKind.Relative));

newButton.Text = "new";

newButton.Click += new EventHandler(newButton_Click);

ApplicationBarIconButton folderButton = new ApplicationBarIconButton(new Uri

("/Images/appbar.folder.rest.png", UriKind.Relative));

folderButton.Text = "folders";

folderButton.Click += new EventHandler(folderButton_Click);

ApplicationBarIconButton syncButton = new ApplicationBarIconButton(new Uri

("/Images/appbar.sync.rest.png", UriKind.Relative));

syncButton.Text = "sync";

syncButton.Click += new EventHandler(syncButton_Click);

//Add the icon buttons to the Application Bar

ApplicationBar.Buttons.Add(newButton);

ApplicationBar.Buttons.Add(folderButton);

ApplicationBar.Buttons.Add(syncButton);

//Create menu items

ApplicationBarMenuItem settingsMenuItem = new ApplicationBarMenuItem

("settings");

settingsMenuItem.Click += new EventHandler(settingsMenuItem_Click);

ApplicationBarMenuItem addaccountMenuItem = new ApplicationBarMenuItem

("add email account");

addaccountMenuItem.Click += new EventHandler(addaccountMenuItem_Click);

//Add the menu items to the Application Bar

ApplicationBar.MenuItems.Add(settingsMenuItem);

ApplicationBar.MenuItems.Add(addaccountMenuItem);

}

应用程序栏可以定义成本地的或者全局的。本地的应用程序栏只能在定义它的页面中使用。这对程序中不同的页面需要不同的应用程序栏来说是很有用的。比如,在程序中创建Email,主页面可能会有create new email和sync,撰写邮件页面可能会有send和delete。所以对两个页面定义不同的应用程序栏是很有必要的。

全局的应用程序栏是一种可以被程序中的所有页面使用的。它定义在程序资源中的App.xaml文件中。创建全局的应用程序栏基本上按照以下步骤。

1. 填加应用程序栏的XAML定义到App.xaml文件的<Application.Resources>节中。

2. 填加下列属性到你需要使用此应用程序栏的每个页面中的<phone:PhoneApplicationPage>节点中:

ApplicationBar="{StaticResource GlobalAppMenuBar}"

应用程序栏的更多信息参考这里

 

后退按钮

所有的Windows Phone都包含一个硬后退按钮。这个按钮允许用户导航到应用程序里的上一页面或者跨不同的应用程序。比如,可以在电子邮件程序里单击一个超链接来打开网页浏览器,然后点击了设备的后退按钮返回到邮件界面。这就是典型的不同程序切换的用户体验,不管是第三方应用还是Windows Phone内置的程序。Windows Phone就是通过这种日志维护的方式记录导航操作来支持后退按钮功能。

下图显示的是设备上的后退按钮,开始按钮和搜索按钮。

clip_image007

后退按钮可以被重写以自定义一些你想要的功能。然后,当你进行这个操作的时候,应该明确用户是如何理解这个后退的。比如,如果你在程序里显示了一个弹出消息,你也许在后退按钮中实现的是退出程序的方法,但用户想要的也许是关闭弹出消息框。

重写后退按钮行为的是PhoneApplicationPage.OnBackKeyPress方法。

下面的示例包含了一个文本框,如果你在文本框输入了内容并且点击设备上的后退按钮,一个消息会提示,“You are about to discard your changes. Continue”。这个行为就是通过重写PhoneAplicationPage.OnBackKeyPress方法实现的。

C#

protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)

{

base.OnBackKeyPress(e);

if(MyTB.Text != string.Empty)

{

var result = MessageBox.Show("You are about to discard your changes. Continue?",

"Warning", MessageBoxButton.OKCancel);

if (result != MessageBoxResult.OK)

{

e.Cancel = true;

}

}

}

运行结果如下图。当用户单击后退按钮时会有消息框显示。

clip_image008

在重写后退按钮的时候最好遵循下面的最佳实践:

1. 在程序中,要考虑到后退按钮在用户当前操作的含义。

2. 如果用户第二次点击后退按钮,应该让默认的行为发生。

3. 在本地导航中避免过度使用后退按钮。

4. 对于一些使用时间比较短的界面,比如登录界面,尽量使用Silverlight的Popup控件显示内容,它只占屏幕的一部分而不是全部。可以在代码中填加PhoneApplicationPage.OnBackKeyPress方法并且设置e.Cancel为true,这样当popup显示的时候就可以通过后退按钮来关闭它。

posted @ 2011-11-01 23:17  哥本哈士奇(aspnetx)  阅读(1673)  评论(0编辑  收藏  举报