创建新的窗体类
到目前为止,我们看到的程序还只是脚本风格,用现有的窗体和控件,快速把窗体放在一起。这种编程风格可用于快速开发单一窗体的应用程序,但是,对于快速创建有多个窗体组成的应用程序,或者创建窗体库以用于其他 .NET 语言时,就会受到限制;在这些情况下,必须采取一种更面向组件(component-oriented)的方法。
通常,创建一个大型的 Windows 窗体应用程序时,有一些窗体需要重复使用;此外,通常希望这些窗体能够相互通信,通过调整彼此的属性或调用彼此的方法。通常是定义新的窗体类,从 System.Windows.Forms 派生,来实现的。清单 8-4 就是这样一个例子,使用第五章介绍的类语法。
清单 8-4 创建新的窗体类型
open System
openSystem.Windows.Forms
// aclass that derives from "Form" and add some user controls
type MyForm() as x =
inherit Form(Width=174, Height=64)
// create some controls to add the form
let label = new Label(Top=8, Left=8, Width=40, Text="Input:")
let textbox = new TextBox(Top=8, Left=48, Width=40)
let button = new Button(Top=8, Left=96, Width=60, Text="Push Me!")
// add a event to the button
do button.Click.Add(fun _->
let form = new MyForm(Text=textbox.Text)
form.Show())
// add the controls to the form
do x.Controls.Add(label)
do x.Controls.Add(textbox)
do x.Controls.Add(button)
// expose the text box as a property
member x.Textbox = textbox
//create an new instance of our form
let form =
let temp = new MyForm(Text="My Form")
temp.Textbox.Text <- "Next!"
temp
[<STAThread>]
do Application.Run(form)
图 8-6 是前面代码运行的结果。
图 8-6. 为便于重用而创建新窗体类型
在前面的例子中,创建的窗体有三个字段:label、textbox 和 button;然后,就可以用外部代码操作这些字段。在示例的最后,创建这个窗体的实例,然后,设置其 textbox 字段的 Text 属性。
事件能公开窗体的接口,非常像字段。由于一些固有的限制,需要更多一点的工作。其思想是这样的:创建一个新的事件,然后把这个事件保存在类的一个字段中,最后,把这个事件的订阅发给筛选过的事件。下面的例子中,筛选 MouseClick 事件以创建 LeftMouseClick:
open System.Windows.Forms
// aform with addation LeftMouseClick event
type LeftClickForm() as x =
inherit Form()
// create the new event
let event = new Event<MouseEventArgs>()
// wire the new event up so it fires when the left
// mouse button is clicked
do x.MouseClick
|> Event.filter (fun e-> e.Button = MouseButtons.Left)
|> Event.add (fun e-> event.Trigger e)
// expose the event as property
[<CLIEvent>]
member x.LeftMouseClick = event.Publish
以这种基于组件(component-based)的方式创建的窗体,无疑要比以更脚本化方式创建的窗体容易使用;但是,在创建用于其他 .NET 语言的窗体库时,仍有缺陷。更多有关创建 F# 库用于其他 .NET 语言的内容,参考第十三章。