UML软件工程组织 |
使用VB.NET的五个技巧 |
作者:陶刚 本文选自:赛迪网 2003年04月10日 |
.NET框架组件太大了,比任何以前所写的封装功能的库都要大。这样有好处,因为它大幅削减了建立应用程序所需编写的代码,但是也使我们不可能完全了解该框架组件。但是我们很容易从中找到一些技巧。 窗体嵌套 经验丰富的Visual Basic开发者知道多文档界面(MDI)应用程序能够包含子窗体,那些子窗体由MDI父窗体管理。但是如果没有MDI的能力你怎样实现包含嵌套窗体?例如一个MDI子窗体也可能需要包含另一个窗体。 有时能够使用用户控件(UserControl)实现这种功能,但是如果你真的需要把一个窗体嵌套进另一个窗体,有多种方法可以实现。窗体衍生自Control类,这意味着它能被放入另一个窗体的控件集合中,使用如下的逻辑:
但是很不幸,这段代码将会导致一个运行时(runtime)异常(见图1)。 图1.试图把一个窗体添加到另一个窗体的控件集合时出现的运行时错误 为了避免这种异常,该窗体的TopLevel属性必须设置为False(见下面的代码)。
图2显示的是使用上面的逻辑实现的一个窗体嵌入另一个窗体。嵌入的窗体有一个标题条(它的颜色是未激活的系统颜色),因此该嵌入窗体能在容器窗体内四处拖动。在图2中,该窗体从它的开始位置(左上角)拖到了右下角。 图2.在容器窗体中有一个嵌入的窗体。嵌入的窗体能在容器窗体中拖动。 通常在显示嵌入的窗体前先设置它的位置。这只需要简单的设置嵌入窗体的Left和Top属性。嵌入窗体的位置与容器窗体是相对的。 与MDI子窗体不同,嵌入窗体能覆盖容器窗体上的控件。图3显示了它们的不同。 图3.嵌入窗体(左)可以覆盖容器窗体上的控件。MDI子窗体(右)不能覆盖MDI父窗体上的控件。 在右边的MDI例子中,没有办法使按钮隐藏在子窗体的后面。但是在左边该按钮被嵌入窗体覆盖了。 当窗体第一次被嵌入时,它将显示在容器窗体上的已存在的控件的后面。当它被点击时,它走向前台并停留在那儿。这会打扰用户,但是能通过插入下面的代码防止这种情况发生:
嵌入的窗体可以包含其它的嵌入窗体,没有实际的限制。图4显示了一个本身包含嵌入的窗体的嵌入窗体。 图4.一个包含嵌入窗体的嵌入窗体 处理数据行(DataRow) Windows窗体中的数据绑定列表框和组合框很节省时间。典型的代码如下(假定已经建立了SqlDataAdapter或者其它部件获取数据):
在这种情况下,代码使用Northwind数据库的顾客记录工作。DisplayMember属性设置为你希望用户在列表框中看到的记录字段,它是customers表的CompanyName。通常ValueMember属性设置为数据表中的一个键字段,对于customer来说是CustomerID。一旦用户选择了列表框中的一行,很容易使用列表框的SelectedValue属性获得键字段:
但是有可能需要一个与被选择项相关的整个数据行对象的引用。例如,如果被选择的行需要被删除,就不知道键了。你需要一个数据行的引用以使用Delete方法。 典型的Visual Basic开发者通常这样想:"我已经得到了该行的键了,我将编写一些逻辑来查找使用该键的行"。这样可以实现,但是有更好的实现方法。可以使用一行代码获取与列表框中选项关联的数据行:
通常该逻辑不会凭直觉出现,即使对经验丰富的开发者。为了解释这是怎样实现的,我把上面的一行拆成几行,下面的代码与上面代码的功能相同:
DataRowView类是数据行的包装,它被多个Windows窗体控件使用。它使得显示与控件中的数据行相关的数据更加容易。当列表框被数据绑定到数据表时(假定列表框中的有些行当前被选定了),列表框的SelectedItem属性保存了一个DataRowView对象。 这意味着我们能把列表框的SelectedItem属性转换到DataRowView对象,这就是上面代码中的第二行实现的。接着DataRowView暴露一个Row属性,它指向被包装的数据行。上面的代码声明了一个数据行并设置了Row属性。 转换对象的类型以访问它的接口的技术在Visual Basic 6.0中不是经常使用,但是在Visual Basic .NET中这是经常的。有了上面的例子后,大多数有经验的开发者迅速跟上了这种技术。 数据行的引用(dr)可用于用任何方式维护行。访问数据行中的任何特定字段是可行的。行中的数据可以被改变,能使数据行的Delete方法把该行标识为删除,或者从数据表的行集合中删除该行。下面的代码标识删除了一行:
使用主键(由ListBox.SelectedValue返回)查找下层数据行的方法需要很多代码,要花很长时间,执行起来更慢。对于刚开始使用Visual Basic .NET的程序员来说花几个小时编码是很正常的。理解上面的技术节约了很多时间,更简单、容易维护代码。 给控件绑定颜色 数据绑定能应用于控件的任何属性。我看到过很多人提到能够绑定文本框的背景颜色到数据项,举个例子,超期的帐号的背景色显示红色。 但是如果你试图使用数据集或者数据表实现该功能,将会遇到问题。数据行只能保持受到限制的数据类型,并且不支持Color类型。如果你不能把颜色存储在数据中怎么能绑定颜色呢? 有些途径可以解决这个问题,但是最简单的是用绑定到自定义数据对象代替绑定到数据表。自定义业务对象的属性可能是Color型的,这样的属性能绑定到控件的BackColor属性。 为了演示,我定义了下面的自定义事务对象:
注意只读的BackColor属性从Balance属性中得到值,并且为负平衡(negative balance)暴露了一个不同的颜色。该类的其它元素很直接。 现在我们建立一个界面来操作这些对象的集合(见图5)。 图5.演示背景颜色绑定的窗体(设计时) 上面的三个文本框都用于保持当前Account对象的数据。它们分别叫txtAccountID、txtCustomerName和txtBalance。显示Load的按钮叫btnLoad,用于载入帐号集合。另两个按钮在记录间导航,分别叫btnBack 和 btnForward。 帐号对象集合可以保持在ArrayList(数组列表)中,因此下面一行代码应该在窗体代码的最前面:
下面是Load方法的Click事件代码。它建立了一些Account对象并把它们放入一个集合中,接着把该集合绑定到文本框。
注意最后两行。txtBalance的Text属性绑定到一个帐号的Balance属性,并且该控件的BackColor属性绑定到帐号对象的BackColor属性。它演示了.NET框架组件绑定一个以上属性到不同数据项。 现在点击btnBack的Click事件,填入一下代码:
启动项目并点击Load按钮。ABC公司的记录出现在文本框中。点击向前按钮,就是XYZ公司记录,同时,txtBalance的背景色变为橙红色(见图6)。 图6.数据绑定窗体显示了一个负平衡记录,引起Balance字段的背景色不同 过了该帐号记录后,该文本框的背景颜色将变回正常色。 Account类不是特别复杂。但是这个例子最少让你看到了怎样绑定不同属性(例如控件颜色)。 修改数据窗体向导 使用数据窗体向导(Data Form Wizard)你能迅速获得文件操作程序窗体。为了使用它,选择Project菜单的Add New Item,接着选择Data Form(数据窗体)。该向导将一步一步帮助你指定希望的数据,并为那些数据建立一个文件操作程序。图7显示了一个从Northwind数据库的Products表中产生的数据窗体。 图7. Northwind Products表的文件维护窗体,它由数据窗体向导产生 但是这种自动生成程序有一个重要的限制。如果被访问的数据有任何字段不能为空(因为数据库大纲不允许空值),那么向导生成的程序不能添加记录。当点击Add按钮时,将出现错误信息,提示记录中的第一个字段不允许为空(如果你没有最新的服务包,你也许看不到该错误信息,但是程序拒绝添加记录)。 该问题是由于数据窗体向导使用BindingContext对象给绑定的数据表添加了一行。下面是btnAdd_Click事件程序失败的代码:
解决方法是为新行略过BindingContext对象。下面是添加新行的典型代码,该代码应该代替上面的一行代码:
在用数据表的NewRow方法获得一个空行时,该代码给不能为空的字段填充值。接着数据表接受新行,通过数据表行集合的Add方法添加新行。 有了这个补丁后,该数据程序能够运行。可以对它进行增强或改变,例如改变SupplierID 和CategoryID字段以从包含供应商和类别的下拉列表中选择。 在.NET框架组件中显示时间 开发过程过程中我们通常对特定代码片运行所花的时间很感兴趣。当然有一些标准程序和代码工具可以查看到它,但是有经验的Visual Basic 6.0开发者有更快的办法。仅仅捕捉开始时间(使用Now关键字)和终止时间(再次使用Now关键字),两种相减,就能知道结果了。 如果使用Visual Basic .NET编写,首先尝试的代码可能是这样的:
但是这段代码的最后一行有语法错误。错误消息是"日期类型没有定义'-'操作符"。这意味着我们不能执行减法。日期数据类型不支持减法操作,那么我们怎么得到两次时间的差别呢? 答案就是使用TimeSpan类。它是用于保持时间段的。上面的代码看起来与.NET框架组件中的相似:
计算使用的是类Date的Subtract方法。最后一行将输出时间的跨度,格式化成小时、分钟和秒(包括秒的小数位)。典型的输出是这样的:
该时间跨度是10秒半。尽管显示了7位小数,但是只能相信两位,但是已经足够了。 结论 .NET是一种有趣的技术。.NET框架组件有超过8000个类!在如此庞大的内容中却很容易找到有用的功能。我希望上面的几个技巧在你的应用程序中能够用到。
|
版权所有:UML软件工程组织 |