页面
我们的Windows Phone应用程序,就像Web应用一样,都是由不同的页面构成的,类似的,我们要考虑的事情就是页面间的切换,伴随着的问题就是不同的页面之间的参数的传递,这些问题已经在上一篇 中解决了。接下来就是一些页面的基本知识。
页面基础
我们在使用vs2010创建一个新的项目的时候,系统自动生成一个MainPage,从这个页面我们可以看到每一个页面都是继承自PhoneApplicationPage。而且每一个页面的布局都分为标题与应用程序名的等和程序员自己定义的部分。
页面的属性中比较常用的是SupportedOrientations,这个属性用来表示页面的存在方向,这个属性的取值有三,分别为Portrait(仅支持竖屏显示)、Landscape(仅支持横屏显示)、PortraitOrLandscape(支持横屏和竖屏切换)。
另一个属性Orientation表示当前页面的方向设置,取值是PageOrientation枚举的值:
- None 未指定任何方向。
- Portrait 纵向。
- Landscape 横向。
- PortraitUp 纵向。
- PortraitDown 纵向。从不使用此方向。
- LandscapeLeft 横向,页面顶部向左旋转。
- LandscapeRight 横向,页面顶部向右旋转。
这里有一个PortraitDown的值,因为没有人会习惯手机倒置并且进行操作,所以一般不会使用这个属性。
既然有上述这样的属性,当然存在着相对应的事件,就是PhoneApplicationPage的OrientationChanged事件,通过监听手机方向的变化来实现一些功能。有一个需要我们注意的地方就是当手机由竖屏转为横屏的时候,页面的布局会发生变化,我们为了防止这种变化给用户带来使用的不悦感,必须设法解决这样的问题。
两种特殊页面
两种特殊的页面Pivot页面和Panorama页面。这两个页面就是Windows Phone为实现其Metro设计理念而增加的的新的用户界面。
Pivot页面
由于大部分的手机都是触摸屏的,使用手势(推拉拖拽)已经是这一种习惯了。传统的触摸屏手机都会实现这样一个功能:在滑动手指的时候,页面会进行切换,但是一般的程序,需要程序员在后台绘制若干个窗口,然后再监听这些窗口,实现手指滑动的时候页面的切换。
而Windows Phone提供的Pivot视图,可以很方便的进行窗口间的切换,更方便的是,这些窗口(其实是一个控件)使用的是一份后台代码,所以不需要过分考虑在窗口切换的时候数据的传递问题。
说的形象一点,这个控件就类似于WinForm的TabControl控件,它的标签名字或者类名就是Pivot,它的子项类似于TabControl中的TabPage,被称为PivotItem,所以在切换的时候就是在不同的PivotItem之间进行切换。
在编码的时候,Pivot对象使用SelectedIndex和SelectedItem来设置或获取当前选中的PivotItem的索引或者对象。
注意:
在使用Pivot页面的时候不要将Header的内容设置的过多,因为这样会导致整体的效果,由于遮挡了后部PivotItem的Header,引起用户不必要的不快感。或者会因此失去此页面可以通过滑动切换页面的提示性效果。
Panorama页面
Panorama页面时Windows Phone引入的一种全新理念视图。它的设计理念是设计者可以使用一个远远大于屏幕尺寸的页面,而用户可以在自己需要的部分获取全部的信息或者功能,当然这是通过拖拽来实现的,它避免了传统意义上的页面间的切换。
为了让Panorama看起来有一个更完整的整体性,可以为Panorama添加一个背景图片,那么在Panorama在滑动的时候更具整体感。
另外,背景图片的要求:高为800像素,宽度大于480像素,但不超过2000像素。
在创建项目的时候,我们可以进行选择,来创建相应的Panorama或者Pivot页面。如
另外一种方式就是在一个普通的页面中插入Panorama或者Pivot控件来达到效果。如果工具箱中没有的话,可以右键“选择项”,找到这两个控件并添加就可以在页面中使用了。但是笔者认为,一个应用程序如果要使用这两种控件的话,要么做成Panorama,要么做成Pivot,不要两种页面混合起来。我也相信没有人会这样做。如:
系统状态栏
Windows Phone页面的上方提供了系统状态栏:SystemTray,用于显示信号强度、电量等信息。但是根据Windows Phone的定义,系统状态栏会按照固定的顺序显示相关信息,并且不允许修改。
可以显示的信息及其相关顺序为:
- 信号强度
- 数据连接
- 未接来电
- 漫游状态
- 无线网络(WIFI)信号强度
- 蓝牙状态
- 铃音模式
- 输入状态(大小写等)
- 电池状态
- 系统时间
在默认状态下,只有系统时间是默认显示的,而其余的指示图标会在页面加载完成后8秒左右显示出来。
另外,我们可以通过设置 “shell:SystemTray.IsVisible”的属性为True或者False来达到控制某一个页面中是否允许系统显示系统状态栏,当然也可以在后台代码中使用SystemTray.IsVisible来设置。
应用程序栏
应用程序栏其实就是传统意义上的菜单栏和工具栏的组合。它菜单项和按钮项(图标项)连个部分,但是分别可以实现点击等功能。
方式一:页面的ApplicationBar
应用程序栏使用的代码是:
<phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="按钮 1"/> <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="按钮 2"/> <shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem Text="菜单项 1"/> <shell:ApplicationBarMenuItem Text="菜单项 2"/> </shell:ApplicationBar.MenuItems> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>
这在每一个页面中都是默认生成的,但是被注释掉了,只要在我们想使用的时候,取消注释并且修改各种值就行了。如显示的字符或图片。
菜单项
对于菜单项
<shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem Text="菜单项 1"/> <shell:ApplicationBarMenuItem Text="菜单项 2"/> </shell:ApplicationBar.MenuItems>
来说,页面中没有硬性的对个数的要求。但是一般意义上,我们习惯设置为5个以内,因为超过5个,在应用程序栏中会出现滚动条,这会影响用户的体验。
图标项
对于图标项,
<shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="按钮 1"/> <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="按钮 2"/>
我们需要找到其图片,在安装虚拟机的时候会默认的存在于我们的计算机中,一般位置在C:\Program Files\Microsoft SDKs\Windows Phone 7.1\Icons中找到,之后将其复制到自己的项目中并指定相应的IconUri就行了。但有一点需要注意,每一个图片的“生成操作”属性应该被设置为“Content(内容)”。
另外要注意的是按钮的数量在这里是有硬性要求的,它规定不能超过4个,因为过多的话会造成界面的混乱,同时不利于操作。
方式二:全局的ApplicationBar
另外一个生成应用程序栏的办法是定义全局的资源,在需要使用的地方引用即可。方法是在App.xaml中的<Application.Resources>标签中定义:
<!--应用程序资源--> <Application.Resources> <shell:ApplicationBar x:Key="myApplicationBar" IsVisible="True"> <shell:ApplicationBarIconButton IconUri="/Images/appbar.check.rest.png" Text="check" Click="ApplicationBarIconButton_Click" /> <shell:ApplicationBarIconButton IconUri="/Images/appbar.close.rest.png" Text="close" Click="ApplicationBarIconButton_Click"/> <shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem Text="check" Click="ApplicationBarMenuItem_Click" /> <shell:ApplicationBarMenuItem Text="close" Click="ApplicationBarMenuItem_Click"/> </shell:ApplicationBar.MenuItems> </shell:ApplicationBar> </Application.Resources>
最后在需要使用的时候,在页面的头标签中添加这样的定义即可,
<phone:PhoneApplicationPage ApplicationBar="{StaticResource myApplicationBar}">
但是要注意,在这里的Click事件是全局性的响应,所以在书写的时候要注意。
例子
下面写一个例子,关于ApplicationBar的使用。
我们新建一个普通的Windows Phone Application项目,在C:\Program Files\Microsoft SDKs\Windows Phone 7.1\Icons中找到这四个图片,
将其添加到项目中新建的文件夹“images”中,同时设置它们的“生成操作”属性为“内容”。首先在MainPage中设置一个ApplicationBar,是其有两个按钮和两个菜单项,提供点击提供当前点击控件的信息。另外添加一个按钮进行页面导航,如下:
<!--ContentPanel - 在此处放置其他内容--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Button Content="页面二" Height="72" HorizontalAlignment="Left" Margin="273,51,0,0" Name="button1" VerticalAlignment="Top" Width="160" Click="button1_Click" /> </Grid>
和
<phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton IconUri="/Images/appbar.new.rest.png" Text="new" Click="ApplicationBarIconButton_Click"/> <shell:ApplicationBarIconButton IconUri="/Images/appbar.minus.rest.png" Text="minus" Click="ApplicationBarIconButton_Click" /> <shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem Text="new" Click="ApplicationBarMenuItem_Click"/> <shell:ApplicationBarMenuItem Text="minus" Click="ApplicationBarMenuItem_Click"/> </shell:ApplicationBar.MenuItems> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>
后台处理代码为:
private void ApplicationBarMenuItem_Click(object sender, EventArgs e) { var mine = (ApplicationBarMenuItem)sender; MessageBox.Show("您点击了"+this.PageTitle.Text+"的ApplicationBarMenuItem:" + mine.Text, "ApplicationBarMenuItem", MessageBoxButton.OK); } private void ApplicationBarIconButton_Click(object sender, EventArgs e) { var mine = (ApplicationBarIconButton)sender; MessageBox.Show("您点击了" + this.PageTitle.Text + "的ApplicationBarIconButton:" + mine.Text, "ApplicationBarIconButton", MessageBoxButton.OK); } private void button1_Click(object sender, RoutedEventArgs e) { this.NavigationService.Navigate(new Uri("/SecondPage.xaml",UriKind.Relative)); }
新增一个页面,在App.xaml中定义全局ApplicationBar,如:
<!--应用程序资源--> <Application.Resources> <shell:ApplicationBar x:Key="myApplicationBar" IsVisible="True"> <shell:ApplicationBarIconButton IconUri="/Images/appbar.check.rest.png" Text="check" Click="ApplicationBarIconButton_Click" /> <shell:ApplicationBarIconButton IconUri="/Images/appbar.close.rest.png" Text="close" Click="ApplicationBarIconButton_Click"/> <shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem Text="check" Click="ApplicationBarMenuItem_Click" /> <shell:ApplicationBarMenuItem Text="close" Click="ApplicationBarMenuItem_Click"/> </shell:ApplicationBar.MenuItems> </shell:ApplicationBar> </Application.Resources>
并书写后台处理:
private void ApplicationBarMenuItem_Click(object sender, EventArgs e) { var mine = (ApplicationBarMenuItem)sender; MessageBox.Show("您点击了全局的ApplicationBarMenuItem:" + mine.Text, "ApplicationBarMenuItem", MessageBoxButton.OK); } private void ApplicationBarIconButton_Click(object sender, EventArgs e) { var mine = (ApplicationBarIconButton)sender; MessageBox.Show("您点击了全局的ApplicationBarIconButton:" + mine.Text, "ApplicationBarIconButton", MessageBoxButton.OK); }
别忘了在第二个页面中添加
<phone:PhoneApplicationPage ApplicationBar="{StaticResource myApplicationBar}">
除此之外再设置一个按钮进行导航,这里就不写了。
最终预期的执行效果为: