9.5 WPF实例--TextReader
前面简单介绍了WPF应用程序的类型和开发模式,本节将通过一个WPF独立应用程序实例TextReader进一步介绍WPF应用程序开发的一般过程。
9.5.1 TextReader界面设计
实例TextReader将开发一个可以打开文本文档的小软件,它具有自动刷新目录、自动判断文件类型是否为文本类型,并查看文本类型的功能,同时还可以查看文件和目录等详细属性。
由于WPF修改了应用程序中窗体的布局方式,使得界面布局更加灵活,但也对开发人员提出了更高的要求,而且使对WPF还不太熟悉的初学者更加不知所措。WPF应用程序的界面设计有以下4个步骤:
(1) 根据软件需求,整理出软件中大致的窗体数量以及各个窗体的功能。在TextReader实例中,需要两个窗体,其中一个是主窗体(也是启动窗体),它具有提供文件导航、文件内容查看功能;另外一个窗体是关于窗体,提供实例程序的版本信息等。
(2)对每个窗体根据功能进行大体布局上的考虑,重点考虑界面分几层、各层的布局方式(网格、绝对定位、流等)、各层区域的划分、每个区域内的布局和进一步分区,逐层进行,直到全部完成。以TextReader主窗体为例,最下层用Grid整体布局,共分3行2列,第1行作为菜单,第3行作为状态栏,第2行则是主界面。主界面区域按列分成左右两部分,左边为目录和文件导航树,右边为文件内容显示区域,如图9-12所示。
(3)重复第(2)步操作,知道界面大致框架基本完成,还涉及控件的选择、控件停靠方向、控件边框位置等细节问题。
(4)基本框架完成,开始进行着色,根据界面风格要求,对各控件进行背景色、前景色、背景图片等外观美化,从下到上,直到满意为止。其中,实例TextReader的界面设计效果如图9-12所示。
注意:界面设计图中只有窗体工作区,不包括窗体标题栏等非工作区内容。
示例代码9-15是该窗体布局的XAML代码,其中还包括了事件处理函数等,这些将在随后的几节中进行介绍,这里主要关心界面的布局和外观代码。其中,<Menu>空间表示菜单;<MenuItem>表示具体菜单项;<StatuBar>表示状态栏;<StatuBarItem>表示具体的状态栏项;<GridSpliter>节点表示一个分隔条,可以调整左右Grid列的宽度;<TreeView>是树形控件,在本例中用来加载目录和文件信息;<RichTextBox>是一个文本编辑框,本例中用来以只读方式加载和浏览文件内容;<TextBox>控件是文本输入框,用来以只读方式显示文件和目录的详细属性。
示例代码9-15:
<Window x: href="http://schemas.microsoft.com/winfx/2006/xaml/presentation">http://schemas.microsoft.com/winfx/2006/xaml/presentation"
<TabControl Grid.Column="1" Grid.Row="1" Margin="14,9,8,9" Name="tabView"
FontSize="15" Background="Tan"> <TabItem Header="属性" Name="tbiProp" Cursor="IBeam" ToolTip="选中文件或目录的详细属性" Background="Tan"> <TextBox Grid.Column="1" Grid.Row="1" Margin="10,10,10,10" Name="tbProp" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible" IsReadOnly="True" FontSize="15" Foreground="Blue" Background="SlateGray"></TextBox> </TabItem> <TabItem Header="文件内容" Background="Tan"> <RichTextBox Name="rtbText" IsReadOnly="True" VerticalScrollBarVisibility= "Visible" HorizontalScrollBarVisibility="Visible" /> </TabItem> </TabControl> <StatusBar Grid.Row="2" Margin="0,0,0,-3" Name="sbMain" Grid.ColumnSpan="2" Height="32" VerticalAlignment="Bottom"> <StatusBarItem Name="sbiFile" Background="Wheat">打开文件...</StatusBarItem> </StatusBar> </Grid> </Window> |
9.5.2 显示子窗体
在应用程序开发过程中,经常需要弹出新的窗体。在WPF中,窗体有两种弹出模式,一种是通过 System.Windows.Window.Show()方法显示新窗体,新窗体和父窗体之间相互独立,可以同时捕获用户操作。另一种是通过 System.Windows.Window.ShowDialog()方法以模式对话框的方式显示新窗体,新窗体捕获用户操作,父窗体在子窗体存在期间不能进行任何操作,常见的属性设置等窗体就是这种模式。
在TextReader实例中,以模式对话框形式显示关于对话框,要显示一个新的窗体大致有以下3个步骤:
(1)创建要显示的新窗体的对象。
(2)初始化要显示的窗体,如果没有需要初始化的数据,则不进行此操作。
(3)通过System.Windows.Window.Show()或System.Windows.Window.ShowDialog() 方法显示新的对话框。
示例代码9-16是TextReader实例中显示About子窗体的具体实现,首先创建WndAbout窗体新对象wnd,然后进行wnd的Owner参数初始化,最后通过ShowDialog()方法显示对话框。
示例代码9-16:
//关于菜单处理函数 |
9.5.3 关闭窗体
在WPF应用程序中,关闭窗体通过System.Windows.Window.Close()方法实现,在调用Close()方法之后,会立即引发窗体的Closing事件,开发人员可以在Closing事件处理函数中取消关闭操作。
如示例代码9-17所示,其中MiExit_Click()方法中通过this.Close()语句关闭当前窗体,而在Window_Closing()事件处理函数中,则通过e.Cancel=true语句取消关闭操作。
示例代码9-17:
//退出菜单事件处理函数 //退出前Closing事件处理函数 |
9.5.4 使用TreeView控件
树形控件是以树形结构表达元素的方式,是比较常用的控件之一,在WPF控件库中,同样提供了树形控件--TreeView。
在WPF中,TreeView控件只是提供显示容器,具体的节点通过TreeViewItem完成,TreeView控件的Items属性表示了它所包含的子节点。TreeViewItem控件是一个可递归的控件,它也用Items属性表示子节点,层层深入,构成一个完整的树形结构。
可以通过TreeView控件的Items属性添加和删除它的子节点,Items属性的每个元素都是object类型,所以可以包含任意类型的元素,TreeView在显示时会自动通过元素的ToString()方法获取要显示的文本。在这一点上TreeViewItem和TreeView是完全一致的。
TreeView控件不包含节点展开和收拢事件(这和Win Form窗体中的Tree控件不同),它包含SelectedItemChanged事件,用来监视树形结构中选中节点的变化。
TreeViewItem控件具有展开(Expanded)事件和收拢(Collapsed)事件,通过这两个事件可以监视节点的展开和收拢,并给出相应的处理。
在TextReader实例中,要显示目录和文件结构,需要用一种典型的树状结构,所以TreeView控件是首选。本例通过以下思路来完成目录的动态加载:
(1)文件系统中的目录和文件都作为TreeView控件中的节点,用TreeViewItem空间表示,而目录和文件的详细路径则保存在TreeViewItem.Tag属性中。
(2)在窗体启动时加载操作系统中所有的逻辑分区(例如,C:/、D:/等),实际上它们都是目录。
(3)监视树中节点的Expanded事件,如果是一个目录第一次展开,则加载该目录下直接的所有子目录和文件,不包括子目录的子目录和文件。
(4)监视TreeView控件的SelectedItemChanged事件,并根据当前选中节点的路径获取目录或文件的详细属性,并显示到界面上。
(5)当双击TreeView控件中的节点时,如果节点是文件,则判断文件类型;如果节点是文本格式文件,则将文本内容加载到界面上。
示例代码9-18是TextReader中与TreeView控件有关的代码,其中LoadLogicDrive()方法将系统中的逻辑分区信息加载到TreeView控件中,LoadDicTree()方法则将选中目录中的子目录和文件加载到该目录节点下。Dic_Expanded()是所有目录节点的Expanded事件处理函数,它首先判断该目录是不是第一次展开,如果是则加载该目录下的信息,否则不加载。
示例代码9-18:
namespace FileViewer /// <summary> //加载系统中逻辑分区信息到目录树 //窗体加载事件处理函数 //节点展开事件处理函数 //选中文件或目录发生变化事件处理函数 //目录树双击事件处理函数 if (tvi == null) //如果节点为空,返回 if (tvi.Items.Count > 0) //是目录,不是文件,返回 string fileName = (string) tvi.Tag; //获取文件名 |
(点击查看大图)图9-13 TextReader目录树运行效果 |
9.5.5 使用RichTextBox控件
文本编辑和阅读是应用软件最常用的功能之一,WPF中提供两个最基本的文本输入控件:TextBox控件和RichTextBox控件。 TextBox控件提供简单的文本编辑和阅读支持,可以进行多行显示,也可以设置字体、字号、颜色等信息,但这些信息并不能保存并记录到文件中,TextBox控件的使用相当简单,这里就不再进一步介绍。
顾名思义,RichTextBox控件也是用于文本编辑和阅读的,但是它比TextBox功能强大,它可以编辑RTF格式的文档信息。要加载文档信息到RichTextBox通常需要以下5个步骤:
(1)准备文件路径、文件类型(如文本格式、RTF格式等)信息,确保文件存在等。
(2)获取基于要显示的RichTextBox控件的TextRange对象。
(3)通过FileString用读取的方式打开文件。
(4)通过TextRange用指定的文件格式从文件流加载数据。
(5)加载完成后关闭文件。
示例代码9-19演示了如何加载文件信息到RichTextBox控件中,其中ViewTxtFile()方法加载文本(Text)格式的文件,ViewRtfFile()方法加载RTF(Rich Text Format)格式的文件。
示例代码9-19:
//加载文件内容到RichTextBox控件 try //异常处理 //加载文件内容到RichTextBox控件 try //异常处理 |
(点击查看大图)图9-14 文件浏览的运行效果 |
9.6 小结
Windows Presentation Foundation(WPF)是.NET 3.0推出的新组件,并且在.NET 3.5中得到增强,本章首先从WPF的基础概念、体系结构开始,让读者了解WPF的基本原理;然后,介绍WPF的开发模式、XAML代码等知识;最后,通过实例介绍WPF独立应用程序和WPF浏览器应用程序的开发过程。
通过本章的学习,读者应该对WPF有一个简单的了解,并能够用WPF开发出简单的应用程序。读者应该掌握以下知识点:
什么是WPF?WPF有什么作用?
什么是XAML?XAML在WPF开发中起到什么作用?
WPF开发模式是什么样的?
如何进行WPF独立应用程序的开发?
如何使用WPF窗体和控件?
在WPF应用程序中应该如何布局?
如何进行WPF浏览器应用程序的开发?
在WPF浏览器应用程序中如何进行页面的导航?
RichTextBox的使用方法。