网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > 软件工程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
本月文章推荐
.Apache中的表格实现剖析(1).
.SOA是企业IT战略热点 怎么评估部.
.献给汇编初学者-函数调用堆栈变.
.“实现能力”与“设计能力”.
.C++ virtual member function FAQ.
.需求工程 研究现状.
.软件自动化测试流程.
.极限建模方法简介.
.XAML开发入门之XAML核心语法.
.软件系统分析的方法和策略.
.LINQ 性能分析系列之传说中的LINQ.
.Windows 工作流活动技术概览.
.Windows 2000 Professional中用命.
.如何利用PVCS进行项目文档管理.
.XAML开发入门之创建XAML应用程序.
.用Robot实现自动化测试.
.面向服务的体系结构SOA概述.
.UML组件图详解.
..NET可复用TCP通信层之消息分派器.
.SOA的进化(一)SOA时间轴.

Avalon应用程序中的导航技术分析

发表日期:2008-3-23



  用户使用微软的新Avalon UI框架组件和XAML(它是用于建立Avalon应用程序的语言)可以建立不同类型的应用程序。本文将介绍Avalon应用程序的导航特性。(请注重,从一开始起,微软就赋予Avalon一个永久的名称:Windows显示框架。在本文中,我们提及的WPF就是指Avalon)。

  WPF应用程序可以被分成两种类型:

  ·独立的Windows应用程序

  ·包含一系列页面的应用程序

  后一种类型(用户在一系列页面中导航)更加普遍。这种类型的应用程序中的导航元素是由Hyperlink(超链接)控件提供。但是Hyperlink控件也有一些缺点,例如向目标页面传递值困难、确定目标页面什么时候返回到调用页面的能力有限、给调用页面传递值也很困难。

  因此,在本文中我将演示如何来处理这些问题;我将建立一个WPF应用程序,它从一个页面导航到另一个页面,在页面之间传递值。

  导航的基础知识

  在深入讲解WPF中的页面导航理论之前,我首先编写一个简单的应用程序,解释一些要害特性。首先,使用Visual Studio 2005建立一个新的WPF项目(我使用的是VB.NET),把这个应用程序命名为AvalonNavigation(图1所示)。

Avalon应用程序中的导航技术分析
图1:在Visual Studio 2005中建立一个新的WPF应用程序

  解决方案治理器如图2所示:

Avalon应用程序中的导航技术分析
图2:解决方案治理器中的内容。你可以看到建立的新项目。

  首先我查看项目中的MyApp.xaml文件。Avalon导航应用程序从<NavigationApplication> 根元素开始。StartupUri属性指定了应用程序执行时载入的页面;在例子中,启动页面是Page1.xaml:

<NavigationApplication x:Class="MyApp"
 XMLns="http://schemas.microsoft.com/winfx/avalon/2005"
 xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"
StartupUri="Page1.xaml"

<NavigationApplication.Resources>
</NavigationApplication.Resources>
</NavigationApplication>
Page1.xaml的内容如下所示:
<Page x:Class="Page1"
 xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
 xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"

<Grid>

</Grid>
</Page>
  现在给项目添加一个Avalon PageFunction项:右键点击解决方案治理器中的项目名称,然后选择“添加新项…”,并选择Avalon PageFunction模板。把页面的名称改成Page2.xaml并点击“添加”(图3所示)。

Avalon应用程序中的导航技术分析
图3:分页。给项目添加一个新的Avalon PageFunction项

  Page2.xaml被加入项目之后,双击它来查看其内容:

<PageFunction x:Class="Page2" x:TypeArguments="String"
 xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
 xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"

<Grid>

</Grid>
</PageFunction>
  Avalon PageFunction是一个基本的WPF页面,只是它会给调用页面返回结果(因此称为页面函数)。图4显示了如何在Page1.xaml中使用Page2.xaml并获取Page2.xaml返回的结果。

Avalon应用程序中的导航技术分析
图4:A到B。现在你可以从Page1.xaml导航到Page2.xaml。

  PageFunction页面有四种类型:

  ·BooleanPageFunction——返回一个布尔型的值;<BooleanPageFunction>元素描述它。

  ·Int32PageFunction——返回一个整型的值;<Int32PageFunction>元素描述它。

  ·ObjectPageFunction——返回一个对象值;<ObjectPageFunction>元素描述它。

  ·StringPageFunction——返回一个字符串;<StringPageFunction>元素描述它。进入讨论组讨论。

  在Page2.xaml中,根元素是<PageFunction>,它并不在上述的四种页面类型之中。<PageFunction>是PageFunction页面的通用版本,你需要用x:TypeArguments属性(在例子中被设置为“String”)来指定它的类型。假如你希望把该页面转换为上述四种类型中的任意一个(例如StringPageFunction),可以简单地改变根元素,如下所示(请注重,x:TypeArguments属性被删除了):

<StringPageFunction x:Class="Page2"
 xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
 xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"

<Grid>

</Grid>
</StringPageFunction>
  但是我现在还是使用原始的<PageFunction>根元素。

  用下面的内容填充Page1.xaml:

<Page x:Class="Page1"
xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"

<StackPanel>

<Button Click="ButtonClick"
HorizontalAlignment="Left"
Margin="10,5,10,5"
Width="120">Go to Page 2
</Button>

<TextBlock Margin="10,5,10,5">
 <Inline Name="txtResult"></Inline>
</TextBlock>

</StackPanel>
</Page>
  基本上,这个页面包含一个用于载入Page2.xaml的按钮控件(图5所示)和一个用于显示Page2.xaml返回值的TextBlock控件(请注重第一次载入的时候TextBlock控件不可见,因为它没有包含任何值)。

Avalon应用程序中的导航技术分析
图5:Page1.xaml。按钮控件载入应用程序的第二个页面。

  在Page1.xaml的后台代码——Page1.xaml.vb中加入的下面的内容:

Partial Public Class Page1
Inherits Page
Private WithEvents p2 As Page2

Private Sub ButtonClick(ByVal sender As Object, _
ByVal e As RoutedEventArgs)

 Dim myApp As NavigationApplication
 Dim navWindow As NavigationWindow

 myApp = CType(System.Windows.Application.Current, NavigationApplication)
 navWindow = CType(myApp.MainWindow, NavigationWindow)

 p2 = New Page2
 p2.InitializeComponent()
 navWindow.Navigate(p2)
End Sub

Private Sub return_handler(ByVal sender As Object, _
ByVal e As ReturnEventArgs(Of String)) _
Handles p2.Return
 txtResult.Text = "Returned: " & e.Result.ToString
End Sub

End Class
  在Page1.xaml.vb中,我添加了两个方法:

  ·ButtonClick——处理按钮控件点击事件。

  ·return_handler——检索Page2.xaml返回的结果。

  假如要导航到某个PageFunction页面,你必须建立目标页面的实例,调用它的InitializeComponent()方法,接着使用Navigate()方法导航到该页面。当目标页面函数返回值的时候,你从该页面的Return(返回)事件中捕捉数据。返回的值可以通过ReturnEventArgs参数检索到。

  现在我们填充Page2.xaml:

<PageFunction x:Class="Page2" x:TypeArguments="String"
xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"

<StackPanel HorizontalAlignment="Left">
<TextBlock Margin="10,5,10,5">
What is your name?</TextBlock>
<TextBox Name="txtName" Margin="10,5,10,5"
Width="200"></TextBox>
<Button Click="ButtonClick" Margin="10,5,10,5"
Width="60"
HorizontalAlignment="Left">Done</Button>
</StackPanel>
</PageFunction>
  Page2.xaml将显示一个文本字符串,后面跟着一个文本框控件和按钮控件(图6所示)。它的目的是提示用户输入名字,接着把这个名字传递回Page1.xaml。


Avalon应用程序中的导航技术分析
图6:Page2.xaml。应用程序的第二个页面将要求用户输入,内容会被传递回Page1.xaml。

  Page2.xaml.vb后台的代码如下:

Partial Public Class Page2
Inherits PageFunction(Of String)

Private Sub ButtonClick(ByVal sender As Object, _
ByVal e As RoutedEventArgs)
 OnFinish(New ReturnEventArgs(Of String)(txtName.Text))
End Sub
End Class
  请注重,Page2类继续自PageFunction类(在XAML页面中匹配了相应的<PageFunction>元素);你也可以指定普通类型(例子中是String)。

  当我们点击Done(完成)按钮的时候,就使用OnFinish()方法返回输入的名字。OnFinish()方法把指定的字符串返回给调用页面(图7所示)。

Avalon应用程序中的导航技术分析
图7:应用程序流程。从页面1到页面2,然后返回,这个过程得到一个名字。

  在这个应用程序中,导航按钮的工作方式与浏览器中的导航按钮的工作方式相似,可以让你向前和向后访问页面(图8所示)。图8中的“untitled”指向Page2.xaml。

Avalon应用程序中的导航技术分析
图8:前进和后退。你可以查看应用程序中页面导航的历史。

  所有载入过的页面都会自动地存储在一个堆栈数据结构(就是journal,导航日志)中。在某些情况下,你可能不希望在导航日志中记录某些页面(例如,为了防止用户不小心导航到了某个作为事务部分的页面,从而破坏了应用程序的流程)。假如要手动从导航日志中删除某个页面,就把它的RemoveFromJournal属性设置为“true”:

' Page2.xaml
Private Sub ButtonClick(ByVal sender As Object, _
ByVal e As RoutedEventArgs)
Me.RemoveFromJournal = True
 OnFinish(New ReturnEventArgs(Of String)(txtName.Text))
End Sub
  这样操作以后,Page2.xaml就不会显示在导航按钮中了(图9所示)。

Avalon应用程序中的导航技术分析
图9:此处没有后退。你可以从导航日志中删掉一个页面。
进入讨论组讨论。
向页面传递数据

  你已经看到了PageFunction页面是如何使用OnFinish()方法把值传递回调用页面。那么怎么把调用页面的值传递给PageFunction页面呢?在例子中,可以给目标PageFunction页面添加一个构造函数来实现。假设你需要给传递一个值,你就必须添加下面的构造函数:

Partial Public Class Page2
Inherits PageFunction(Of String)

Public Sub New()

End Sub

Public Sub New(ByVal data As String)
' 处理输入的数据
End Sub

Private Sub ButtonClick(ByVal sender As Object, _
ByVal e As RoutedEventArgs)
 Me.RemoveFromJournal = True
 OnFinish(New ReturnEventArgs(Of String)(txtName.Text))
End Sub

End Class
  请注重,你必须添加一个空的构造函数,否则在编译的时候就会碰到错误。同时,你可以根据自己的需要添加多个构造函数,只要它们的参数(信号)不同。

  为了给目标页面传递数据,在调用页面中你必须简单地提供必要的参数。

p2 = New Page2("the string to pass into")
p2.InitializeComponent()
navWindow.Navigate(p2)
  线性导航

  现在你已经知道了WPF应用程序中页面导航的一些基础知识了,现在我们来看一些重要的细节信息。在WPF中有两种主要的导航类型:

  ·线性的(Linear)

  ·层次的(Hierarchical)

  在线性导航中,所有的页面都串在一起,一个接一个地载入。图10显示了用线性方式链接在一起的三个页面。对于层次导航,页面链接的方式类似于树结构。在下一部分中我们会讨论层次导航的问题。


Avalon应用程序中的导航技术分析
图10:线性导航。应用程序的这三个页面是线性关系。

  我现在建立一个简单的应用程序,演示线性导航是如何工作的。使用Visual Studio 2005建立一个新的WPF(Avalon)导航应用程序。有了默认的Page1.xaml页面中之后,再添加两个PageFunction页面,分别是Page2.xaml和Page3.xaml。我同时还会演示不同的PageFunction页面类型。

  填充Page1.xaml页面:

<Page x:Class="Page1"
 xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
 xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"

<DockPanel>
<StackPanel DockPanel.Dock="Left"
Background="LightBlue">
<TextBlock Margin="10,10,10,10">
Page 1</TextBlock>
</StackPanel>

<StackPanel DockPanel.Dock="Right"
Background="LightYellow">
<TextBlock Margin="10,10,10,10">
Enter your name</TextBlock>
<TextBox Name="txtName" Margin="10,10,10,10"
Width="200"
HorizontalAlignment="Left"></TextBox>

<Button Click="ButtonClick" Name="BTnNextPage"
 Margin="10,10,10,10" Width="80"
HorizontalAlignment="Left">Next Page</Button>
<Button Click="ButtonClick" Name="btnExit"
 Margin="10,10,10,10" Width="80"
HorizontalAlignment="Left">Exit</Button>

<TextBlock Margin="10,10,10,10">
<Inline Name="returnString" />
</TextBlock>
</StackPanel>
</DockPanel>
</Page>
  图11显示了Page1.xaml载入时候的样子。

Avalon应用程序中的导航技术分析
图11:Page1.xaml。新应用程序的第一个页面,它将使用线性导航。

  在后台代码Page1.xaml.vb中添加下面的内容:

Partial Public Class Page1
Inherits Page
Public WithEvents nextPage As Page2

' 用于保存输入的名字
Private Shared _Name As String

Private Sub OnLoaded(ByVal sender As Object, _
ByVal e As RoutedEventArgs) Handles Me.Loaded
 txtName.Text = _Name
End Sub

Private Sub ButtonClick(ByVal sender As Object, _
ByVal e As RoutedEventArgs)

Dim myApp As NavigationApplication
Dim navWindow As NavigationWindow

myApp = CType(System.Windows.Application.Current, NavigationApplication)
navWindow = CType(myApp.MainWindow, NavigationWindow)

' 导航到下一个页面
If sender.Equals(btnNextPage) Then
' 保存输入的名字
_Name = txtName.Text

nextPage = New Page2
nextPage.InitializeComponent()
navWindow.Navigate(nextPage)
End If

' 退出应用程序
If sender.Equals(btnExit) Then
System.Windows.Application.Current.Shutdown()
End If

End Sub

Private Sub nextPage_Return(ByVal sender As Object, _
ByVal args As StringReturnEventArgs) Handles _
nextPage.Return
' 显示后一个窗体中输入的字符串
returnString.Text = "From Page 2: " & args.Result.ToString
End Sub

End Class
  在这个页面中需要重点注重的是:

  ·点击Next Page(下一页)按钮或Exit(退出)按钮的时候会调用ButtonClick()方法。

  ·假如点击了Next Page按钮,应用程序将导航到Page2.xaml。假如点击了Exit按钮,应用程序将退出。

  ·在应用程序导航到Page2.xaml之前,用户输入的名字必须保存在一个共享(shared)变量中。这是因为在两个页面之间导航(无论是编程或使用导航按钮)的时候,页面的状态是不会保存的。因此你必须维护自己的状态信息。

  ·无论页面在什么时候载入都会调用OnLoaded()方法,因此这是设置控件初始值/状态的位置。

  ·当Page2.xaml返回值的时候调用nextPage_Return()方法。

  填充Page2.xaml:


<StringPageFunction x:Class="Page2"
xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"

<DockPanel>

<StackPanel DockPanel.Dock="Left"
Background="LightBlue">
<TextBlock Margin="10,10,10,10">
Page 2</TextBlock>
</StackPanel>

<StackPanel DockPanel.Dock="Right"
Background="LightYellow">

<TextBlock Margin="10,10,10,10">
Enter your company name</TextBlock>
<TextBox Name="txtCompanyName"
Margin="10,10,10,10"
Width="200" HorizontalAlignment="Left">
</TextBox>

<DockPanel>
<Button DockPanel.Dock="Left"
Click="ButtonClick"
Name="btnPreviousPage"
Margin="10,10,10,10"
Width="80" HorizontalAlignment="Left">
Previous Page</Button>

<Button DockPanel.Dock="Right"
Click="ButtonClick"
Name="btnNextPage" Margin="10,10,10,10"
Width="80" HorizontalAlignment="Left">
Next Page</Button>
</DockPanel>

<Button Click="ButtonClick" Name="btnExit"
Margin="10,10,10,10" Width="80"
HorizontalAlignment="Left">Exit</Button>

<TextBlock Margin="10,10,10,10">
<Inline Name="returnString" />
</TextBlock>

</StackPanel>
</DockPanel>
</StringPageFunction>
  请注重,Page2.xaml是一个StringPageFunction,这意味着它会给调用页面返回一个字符串值。图12显示了Page2.xaml页面载入时候的样子。

Avalon应用程序中的导航技术分析
图12:Page2.xaml。应用程序的第二个页面,它给第一个页面返回一个字符串。

  在后台代码Page2.xaml.vb中输入下面的内容:

Partial Public Class Page2
Inherits StringPageFunction
Public WithEvents nextPage As Page3

' 用于保存用户在页面中选择的公司名称
Private Shared _CompanyName As String

Private Sub OnLoaded(ByVal sender As Object, _
ByVal e As RoutedEventArgs) Handles Me.Loaded
 txtCompanyName.Text = _CompanyName
End Sub

Private Sub ButtonClick(ByVal sender As Object, _
ByVal e As RoutedEventArgs)

 Dim myApp As NavigationApplication
 Dim navWindow As NavigationWindow

 myApp = CType(System.Windows.Application.Current, NavigationApplication)
 navWindow = CType(myApp.MainWindow,NavigationWindow)

 ' 导航到下一页
 If sender.Equals(btnNextPage) Then
  _CompanyName = txtCompanyName.Text

  nextPage = New Page3
  nextPage.InitializeComponent()
  navWindow.Navigate(nextPage)
 End If

 If sender.Equals(btnPreviousPage) Then
  OnFinish(txtCompanyName.Text)
 End If

 ' 退出应用程序
 If sender.Equals(btnExit) Then
  System.Windows.Application.Current.Shutdown()
 End If

End Sub

Private Sub nextPage_Return(ByVal sender As Object, _
ByVal args As BooleanReturnEventArgs) Handles _
nextPage.Return
 ' 显示后一个窗体中输入的字符串
 returnString.Text = "From Page 3: " & args.Result.ToString
End Sub

End Class
  基本上,Page2.xaml.vb与Page1.xaml.vb非常相似,除了点击Previous Page(前一页)按钮的时候,它使用OnFinish()方法给调用页面返回输入的公司名称。Next Page按钮引起应用程序导航到Page3.xaml。

  最后,填充Page3.xaml:


<BooleanPageFunction x:Class="Page3"
xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"

<DockPanel>
<StackPanel DockPanel.Dock="Left"
Background="LightBlue">
<TextBlock Margin="10,10,10,10">
Page 3</TextBlock>
</StackPanel>

<StackPanel DockPanel.Dock="Right"
Background="LightYellow">

<TextBlock Margin="10,10,10,10">
Single?</TextBlock>

<RadioButtonList Margin="10,10,10,10">
<RadioButton Name="rbTrue">True</RadioButton>
<RadioButton Name="rbFalse">False
</RadioButton>
</RadioButtonList>

<DockPanel>
<Button DockPanel.Dock="Left"
Click="ButtonClick"
Name="btnPreviousPage"
Margin="10,10,10,10"
Width="80" HorizontalAlignment="Left">
Previous Page</Button>
</DockPanel>

<Button Click="ButtonClick" Name="btnExit"
Margin="10,10,10,10" Width="80"
HorizontalAlignment="Left">Exit</Button>

</StackPanel>
</DockPanel>
</BooleanPageFunction>
  请注重Page3.xaml是一个BooleanPageFunction,它会给调用函数返回一个布尔型结果。图13显示了Page3.xaml载入时候的样子。

Avalon应用程序中的导航技术分析
图13:Page3.xaml。这个应用程序的最后一个页面,它询问一个简单的布尔型值并返回第二个页面。

  在后台代码Page3.xaml.vb中添加下面的内容:

Partial Public Class Page3
Inherits BooleanPageFunction

' 用于保存页面中选择的状态
Private Shared _Status As Boolean

' 示例事件处理程序
Private Sub OnLoaded(ByVal sender As Object, _
ByVal e As RoutedEventArgs) Handles Me.Loaded
 If _Status = True Then
  rbTrue.IsChecked = True
 Else
  rbFalse.IsChecked = True
 End If
End Sub

Private Sub ButtonClick(ByVal sender As Object, _
ByVal e As RoutedEventArgs)

If sender.Equals(btnPreviousPage) Then
 If rbTrue.IsChecked = True Then
  _Status = True
 Else
  _Status = False
 End If
 OnFinish(_Status)
End If

' 退出应用程序
If sender.Equals(btnExit) Then
 System.Windows.Application.Current.Shutdown()
End If
End Sub
End Class
  现在你可以运行应用程序并跟踪工作流程(图14所示)。

Avalon应用程序中的导航技术分析
图14:应用程序流程。这个线性应用程序的三个页面按页面1、2、3的次序进行,按相反的次序返回。
进入讨论组讨论。
层次导航

  在带有层次导航的WPF应用程序中,用户可以根据自己的选择访问页面。图15显示了一个典型的层次导航应用程序。请注重,每个页面都可以分支出多个页面(根据需要),但是每个页面退出的时候,它将返回调用自己的那个页面。

Avalon应用程序中的导航技术分析
图15:三个页面的层次。这个层次导航的应用程序的页面2和3返回页面1。

  图16显示了图15所示的分层导航应用程序的一个示例实现。在第一个页面中,用户可以输入名字并选择国家,它可以点击“Select Country”(选择国家)按钮载入第二个页面。假如要选择行业,就点击“Select Industry”(选择行业)按钮载入第三个页面。选择国家和行业的页面都返回第一个页面(Page 1)。


Avalon应用程序中的导航技术分析
图16:两个子页面。层次导航应用程序的一种实现。

  在你作出选择之后,结果就显示在主页面上,它是整个应用程序的主页面(图17所示)。

Avalon应用程序中的导航技术分析
图17:返回到开头。其它页面中输入的数据显示在Page1.xaml中了。

  在本文中,你看到了Avalon分页应用程序的概述和两个简单的例子。同时你还看到了五种可供使用的PageFunction页面类型。进入讨论组讨论。

上一篇:深入探讨.NET中的钩子技术 人气:436
下一篇:消息与.Net Remoting的分布式处理架构 人气:495
浏览全部软件工程的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐