首页 > 代码库 > 第八章 用户界面(二)
第八章 用户界面(二)
第八章 用户界面(二)
在 WinForm 上使用控件
控件就是类,派生自 System.Windows.Forms.Control,由此类派生出的任何类都能显示在窗体上,只要将它添加到窗体对象的 Controls 集合中。
现在我们看一下用控件画树形的方法。WinForms 库定义了 TreeView 类,这是专门用于显示树形结构的;自然,我们就用这个控件来显示树。使用 TreeView,需要创建它的实例,并设置属性、调用方法,对它进行配置。最重要的,是将需要显示的结点添加到 Nodes 集合中。这个控件准备好以后,就可以将它添加到窗体的 Controls 集合。
TreeView 类用 TreeNode 对象表示结点,因此,我们定义函数 mapTreeToTreeNode,递归遍历树形结构,创建 TreeNode 图形。清单 8-2 中的程序产生图 8-3 的树。
清单 8-2 用控件 TreeView 画树
openSystem.Windows.Forms
//The tree type
type ‘a Tree =
|Node of ‘a Tree * ‘a Tree
|Leaf of ‘a
//The definition of the tree
let tree =
Node(
Node(
Leaf "one",
Node(Leaf "two", Leaf"three")),
Node(
Node(Leaf "four", Leaf"five"),
Leaf "six"))
// Afunction to transform our tree into a tree of controls
let mapTreeToTreeNode t=
let rec mapTreeToTreeNodeInner t (node :TreeNode) =
match t with
| Node (l, r) ->
let newNode = new TreeNode("Node")
node.Nodes.Add(newNode) |> ignore
mapTreeToTreeNodeInner l newNode
mapTreeToTreeNodeInner r newNode
| Leaf x ->
node.Nodes.Add(new TreeNode(sprintf "%A" x)) |> ignore
let root = new TreeNode("Root")
mapTreeToTreeNodeInner t root
root
//create the form object
let form =
let temp = new Form()
let treeView = new TreeView(Dock = DockStyle.Fill)
treeView.Nodes.Add(mapTreeToTreeNode tree)|> ignore
treeView.ExpandAll()
temp.Controls.Add(treeView)
temp
Application.Run(form)
//form.Show()
图 8-3. 用 TreeView 控件显示树
这段代码大约只有清单 8-1 (自己画树)的一半,还有更多的功能,因为,它可以折叠树中你不感兴趣的部分,这极大地改进了以可管理的方式显示树的大小。
在这个例子中,使用“停靠(Dock)风格”控制控件的外观。即,设置控件的 Dock 属性为一个 DockStyle 枚举值。停靠的控件能更可能占用窗体上的可用空间,如果使用 DockStyle.Left 属性,控件就停在左边;如果使用DockStyle.Right,则停在右边;DockStyle.Top;则停在顶部;DockStyle.Bottom,则停在底部;DockStyle.Fill,则充填整个窗体。如果只有几个控件时,这非常好,因为它有很好的动态效果,当用户调整大小的窗体时,控件的大小也将调整。然而,当有大量控件时会有问题,因为很难用这种方法将大量的控件完美地组合在一起。例如,如果有两个控件都停在左边,就很难确定到底哪一个停靠在最左边,应该占用左边多大的地方。当有大量控件时,更好的方法是要明确地用 Top 和 Left 属性控制其布局。用 Anchor 属性可以创建动态效果,把控件锚定(anchor)在窗体的边缘。下面的例子创建了一个有文本框的窗体,文本框的大小会随着窗体大小的改变而改变:
open System
openSystem.Windows.Forms
let form =
// create a form
let temp = new Form()
// create a text box and set its anchors
let textBox = new TextBox(Top=8, Left=8, Multiline=true,
Width=temp.Width -30, Height=temp.Height-52,
Anchor = (AnchorStyles.Left |||
AnchorStyles.Right |||
AnchorStyles.Top |||
AnchorStyles.Bottom))
// add the text box to the form and return the form
temp.Controls.Add(textBox)
temp
[<STAThread>]
do Application.Run(form)
//form.Show()
[
与原文略有改变,现在文本框为多行模式。
]
然而,这种方法使用控件并不总是令人满意的。这里是只显示了一个控件,而通常在一个窗体上,会有十多个控件,甚至上百个。如果要写出所有的控件创建、配置代码,既单调,也容易出错。为了解决这种问题,Visual Studio 提供了窗体设计器,可以可视化地创建窗体。
然而,到现在这止,还没有针对 F# 的设计器,因此,下一节我们讨论F# 如何使用 C# 设计器创建的窗体。
对于 WinForm 的程序员,使用控件的一个困难在于,如何从众多控件中进行选择。在这一章中,我们只讨论了一个控件。然而,说到学习,没有什么可以取代经验。MSDN 库(http://msdn.microsoft.com)提供了一个很好的参考,但是,它的信息量对于这些新主题也很难让人满意。因此,我把一些最有用的部分进行了汇总,列在表 8-3 中,有助于使用学习曲线变得平坦一些。
表 8-3 WinForm 常用控件及用法
控件 | 描述 |
Label | 显示文本信息。 通常,大多数其他控制应附带 Label,以说明其用途。在 Label 的 Text 属性的文本中加 &,会使其后的一个字母有下划线,通过按键可以跳到与此 Label 相关(即 tab 序号的下一个)的控件,方法是按Alt+<字母>。这极大地提高了应用程序的可用性。 |
TextBox | 用于输入文本的框。 默认情况下文本框是单行,如果将 Multiline 属性设置为 true,可以支持多行;根据自己的喜好,也可以选择 WordWrap 和 ScrollBar 属性;如果想让文本框中显示的文本可以复制、粘贴,可以通过设置 ReadOnly 属性实现。 |
MaskedTextBox | 这个控件与文本框有许多相似之处。 通过设置 Mask 属性,可以限制用户输入的数据。 |
Button | 按钮控件,用户可以单击。 像 Label 控件一样,在按钮的 Text 属性的文本中加 &,使其后的一个字母有下划线,通过按键可以跳到此按钮,方法是按 Alt+<字母>。这极大地提高了应用程序的可用性。 |
LinkLabel | 这个控件的名字有点误导,它不像标签,而更像按钮,看起来像 HTML 链接。这个控件非常适合于网站环境,当单击这个按钮,打开页面。 |
CheckBox | 选择框控件。用于选择一组不互斥的选择项。 |
RadioButton | 与 选择框控件相似,但选择项是互斥的。 放在同一个容器中的选择项自动互斥。容器通常是窗体。 |
DateTimePicker | 从下拉的日历中选取日期。 |
MonthCalander | 月历。 |
ComboBox | 组合框,用户可以从下拉列表中选择。通过数据绑定显示动态数据集(在第九章更细讨论)。 |
ListBox | 列表框,与组合框相似,只是列表项显示在窗体上,而不是在下拉列表中。如果窗体上有大量的空间可以用这个控件。 |
DataGridView | 数据网格视图,虽然可以显示任何表格数据,但是更适宜显示数据库表。应该用这个控件代替以前的 DataGrid(到第九章会进一步讨论)。 |
TreeView | 树视图,这是另一个适合显示动态数据的控件,最适合显示树形数据。 |
ProgressBar | 进度条,对于长时间运行的任务,给用户以反馈是极其重要的。 |
RichTextBox | 显示和编辑富文本,比标准的文本框有更多的格式。 |
WebBrowser | 显示 HTML 文档,因为很多信息是以 HTML 格式提供的。 |
Panel | 把窗体分成不同的部分,配合 HScrollBar 和 VscrollBar 更有效。 |
HScrollBar | 水平滚动条,使 Form 或 Panel 容纳更多的信息 |
VScrollBar | 垂直滚动条,使 Form 或 Panel 容纳更多的信息 |
TabControl | 带选项卡的用户控件 |