日期:2009-10-21  浏览次数:20465 次

ESTD 也可以确认存在数据集中的数据,例如当用户完成每个控件或每行数据时。在你改变数据时,DataTable的事件ColumnChanging、ColumnChanged、RowChanging和RowChanged就被引发了。如果你是在ESTD而不是UI本身中处理这些事件,你可以在运用ESTD的任何地方进行一致性的确认。如果在ColumnChanging事件中引发了一个错误,而且你用的是Windows Forms,用户将陷入困境。所以用这种方法时要小心——它意味着数据层在命令UI的行为。
你可能想从强类型的数据集里的DataRow类派生,并重载属性以提供确认。这么做不行,因为你不能阻止UI程序员绕过你的属性,直接访问表。
正如Andrew J.Brust和Bill Wagner在他们的文章中讲述的,每个控件有一个DataBindings集,里面包含成对的控件属性/数据元素(见资源)。你可以捆绑到任何控件的任何属性。属性表(grid)提供了普通的绑定, 如Text属性。ESTD继承了一个强类型的数据集,所以你可以在设计时直接进行捆绑。
在设计时进行数据绑定有些缺陷,所以一般你想在代码中指派你的绑定(见列表3)。如果你在设计时继承了一个窗体,该窗体包含在属性表里设置的数据绑定,那么当你在设计器中打开你派生的窗体时,就会出现一个错误,因为你试图将你的控件捆绑到设计器中不存在的数据。这是因为基本窗体在设计器中被实例化了,而且基本窗体在设计时的属性是在一个由它的构造器调用的程序中设置的。
而且,打开Windows Forms无论如何不会很快。通常,你可以打开窗体,收集一些用来读取数据的信息,然后读取数据。这就形成了一个更直接的用户界面。在可下载的程序中就用了这个方法,它使你可以更容易地研究代码(见列表3,数据绑定窗体的改进版本)。
管理你的 CurrencyManagers
绑定数据的定位是由从BindingManagerBase派生的CurrencyManager来处理的。 窗体在它的BindingContext 属性中有一个或多个currency managers。单个控件的BindingContext(除了容器控件外)只是指明容器的BindingContext。如果你定义了一个数据绑定,系统检查在容器(通常是窗体)的BindingContext中的currency manager,如果需要,就创建它。这会导致失败,因为稍微不同的定义都会产生一个另外的currency manager,而且绑定到不同curency manager的项目不能自动地同步。如果你不想让特殊的控件同步,就用一个DataView来强行生成一个新的currency manager,而不用重新指定BindingContext。
你不能给一个属性进行多个绑定,否则会产生运行异常。运用AddBinging方法来防止由于不留心在属性表里设置了绑定而产生的运行异常。
一个组合框将currency managers用于它的内容和当前选项。如果这两个currency managers是一样的,对组合框中的项目进行选择就是重新定位了数据,并且使绑定到那个currency manager的其它控件同步。所附程序中的cboPos 组合框说明了这种方法,而cboCountry 组合框说明了对两种不同的currency managers的更普通的用法。



所附程序中包含一个toolbar, 带有一个更新的VB6 DataControl的用户界面。 Toolbar的ButtonClick事件显示了用ESTD进行加载和保存是多么简单。它也显示了如何明确地得到currency manager并用它来控制它在底层DataTable或DataView中的位置。 你可以根据用来创建currency manager的值从BindingContext中得到它,但是任何改变都会形成一个新的currency manager,使你的引用变得没用了。如果你从一个绑定控件的DataBindings集里直接得到currency manager,会更加可靠:
cm = txtCompanyName. _   DataBindings("Text").BindingManagerBase

我略过了InitializeBinding方法中的HookValidation方法调用。为了引发ColumnChanging事件,当前的编辑必须是完成的。在一些情况下,用户希望达到这样的状态。要解决这个问题,可以在用户完成对一个控件的编辑时,明确调用currency manager的EndCurrentEdit方法。调用HookValidation方法可以确保始终调用该control_Validating事件处理程序。
最后,我讲一下ErrorProvider,它是Windows Forms的最好的功能。 虽然这个很酷的控件并不起作用,除非你很好地设置它,但是它的确值得你这么做。ErrorProvider是一个Windows Froms的扩展机制(extender),它可以在任何控件的旁边显示一个带有无效数据的图标。你需要的唯一的代码就是在窗体的InitializeBinding方法中显示的绑定代码和在ESTD的ColumnChanging事件中的确认代码。在所附项目的Contact Name中输入一个数字(如9),看看它是如何工作的。注意,当你改变记录时,错误图标只显示在有错误的记录上。
当你将一个ErrorProvider扩展机制的实例添加到你的窗体并设置它的绑定时,它监控绑定表的每行的ColumnError。如果ColumnError包含文字,一个图标就会出现在绑定到那一栏的任何控件旁边,并包含一个带有 ColumnError文本的tooltip(见列表2 中的ColumnChanging事件)。
用ADO.NET简化 Parenting
在ADO.NET出现前,几个很难实现的功能现在都变得很容易了。例如,当父子关系是建立在由数据库生成的一个键(key)上时,数据集自动生成一个临时的键。默认情况下,这种关系是层叠式变化的,所以当数据库指派一个实际的键时,那个键就自动用于子记录了。另外,如果你为数据库自动增量的栏将AltoIncrementSeed和AutoIncrementStep都设置成 –1,你可以避免一些可能的错误。
通过在CustomerOrderDataAccessor组件上的SQLConnection中包含一个连接字符串(改变用户名/密码,使其在你的服务器上有效),我已经将可下载的程序简化了。实际上,你应该把这个信息包含在一个配置文件中。通过ConfigurationSettings类和动态的属性,配置文件现在很容易操作。
但是,在.NET中不是所有的事情都更容易了。例如,给一个data grid添加图象或组合框,就需要创建一个新的类。所附程序中有这样一个例子,你可以去研究一下。
如果你用的是Web Forms,试一下Web Forms服务器的server control validators。你可以得到一个结构,其规则来自你的ESTD, 并可以用它来定义validators。你可以将XML约束用于XML数据

Web Forms也更适合用一次性读取的数据来准备HTML。如果数据只用在一次性读取中,你可以通过运用一个data reader来加速。Data reader比data set更难使用,但如果一个data reader符合你的设计,你仍然可以用一个n层结构。你只需要给现有的ESTD增加一个DataReader属性即可(在这种情况下,你不用填充ESTD)。或者你可以创建一个并行的DataReader类,并在中间层中包含三个对象:一个reader对象、一个ESTD对象和一个两者都运用的商业对象。
这只是对.NET中的数据绑定的一个初步的研究。随着项目的发展,你可能会尝试更多的方法。你可以根据你的需求扩展底层框架结构。为了构建一个稳固的底层框架,你应该为任何任务或代码片段提供一个逻辑的位置,然后确信并行的任务尽可能多地共享代码。通过对你的底层框架进行最小量的培训,一个新的程序员就可以准确的预测任何代码的位置。
这种结构的回报是巨大的,因为它可以对并行的商业需求进行投资。如果有一天,你计划部署拥有几百万用户的产品,但当前你只有一个开发人员,六位销售人员,没有预算,你仍可以投入到这个计划中,做出你的产品,并根据实际需求发展它。要移植到n层结构中,你不需要大量地重写代码——只要你的产品是建于一个稳固的底层框架上的。

关于作者:
Kath