Visual Basic .NET中多 Windows 窗体的同步

2008-04-09 04:48:32来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折


原著:Ken Spencer

翻译:小刀人



原文出处:MSDN Magazine April 2004 (Advance Basics)

原代码下载:AdvancedBasics0404.exe(135KB)

我用单个窗体的多实例构建一个 Windows 窗体应用程序。我想把它写成 这样一个程序:对该窗体任何一个实例的操作都会在所有其它实例上反映出来。我该怎么做?

这是一个有趣的问题。我保证某些聪明的编程好手会建议我使用委托。在这种事情发生之前,让我们 先探究一下这个问题的几种解决方案。
  假定我有两个窗体,每个窗体都有两个 textbox 控件:txt1stData 和 txt2ndData。我怎样才能保持这两个窗体中的控件同步呢?对于我们讨论的问题来说,有两个或十个窗体都不重要,问题是相同的。
  第一个办法相对简单。事实上,它甚至比我们直接使用委托更为简单,我想委托有时会给人用牛刀杀鸡的感觉。首先,我建立一个类它包含我希望与应用程序中的所有窗体共享的属性(参见 Figure 1)。例如,MyData 和 MoreData 拥有每个窗体都能显示的数据。我将很快回到这个类来。
  第二,正如我早先提到的我用相同的控件(txt1stData 和 txt2ndData)建立了两个窗体。你可以参考 Figure 2 的布局。两个窗体都有完全相同的数据,并且我将很快解释为什么。


Figure 2 窗体布局

下面,我建立一个名为 modGeneral 的模块并加入下面一行代码:

Friend DataStuff As DataClass 
  这一行代码为我的新类 DataClass 创建了一个友元变量,使你可以完全访问程序集,对这个简单例子来说,也就是指完整的应用程序。然后我添加了下面的代码到 Form1 的 Load 事件:
DataStuff = New DataClass Me.txt1stData.DataBindings.Add("Text", DataStuff, "MyData") Me.txt2ndData.DataBindings.Add("Text", DataStuff, "MoreData") 
  第一行建立一个 DataClass 新实例。下面两行代码将数据绑定到 textbox 控件。对这个窗体而言,就这么些操作!
  现在,你怎样让它们与 Form2 和其它窗体上的数据同步呢?将下面两行加入到 Form 2 的窗体load 事件中去:
Me.txt1stData.DataBindings.Add("Text",DataStuff, "MyData") Me.txt2ndData.DataBindings.Add("Text",DataStuff, "Moredata") 
  这个方法容易确保所有窗体上的几乎任何类型的数据处于同步状态。你可以简单地将控件绑定到某个类的相同实例上,这就行了。
  现在来看另一个方法。我创建了一个名为 frmBase 的新窗体。这时我在上面放一个 textbox (txtNextData)和 label。我想 让应用程序的每个窗体都共享这个 textbox 和 label,并且我希望它们互相之间保持同步,于是我重建这个工程。通过从新的 frmBase 中的继承 ,我创建了 Form1 和Form2,因此它们继承了所有新的控件。但是我怎样能保持这些控件同步呢?这时必须写一点代码去达到此效果,这些代码在单个的类中,通过简单地调用一个函数而被复用。
  Figure 3 中的代码展示了这个称为 modGeneral 模块。它的第一个任务是定义两个变量:MyForms 和 localNextData。MyForms 是一个 集合,它将包含我想要同步的窗体列表。localNextData变量将储存所有我想要在窗体里显示的数据。注意这些变量可以驻留于某个类中而不是某个模块里。
  AddForm 过程来自 modGeneral,带一个窗体实例参数,并将其加入 MyForms 集合中。我将在UpdateControlsNextData 过程中使用这个 集合以决定哪些窗体要更新。AddForm 也调用UpdateControlsNextData 来确保一个新窗体是用正确的数据更新的。
  modGeneral 中的其它代码是 NextData 属性。这些属性的 set 存取器更新 localNextData 并也调用 UpdateControlsNextData 去同步所有窗体。这时所有我需要做的是 在想要改变它时设置 NextData,通过调用 UpdateControlsNextData,所有窗体将被更新。
  第三个方法是定制链接,它是第二个方法的精华版。我创建它以获得多一些窗体控件处理的灵活性。例如,我只想跟踪和处理某些窗体,这些窗体包含必须同步的控件。这个方法 还可以让我自己定义拟同步的控件,并且只处理这些控件的窗体。
  我为这个办法添加了另一个模块 (modGeneralv2),如 Figure 4 所示。该模块包括一个集合(MyFormsToUpdate),其中包含所有我想要同步的窗体。这个模块 还有一个新的数组 (ControlsToUpdate),它提供一个我要同步的控件列表。该数组的定义如下:
Private ControlsToUpdate() As String = _ {"txtCustomer", "txtAddress", "txtName"} 
  这个模块里有一个新的替代 AddForm 的改良版本,叫做 AddFormToUpdate。该方法工作方式与AddForm 类似,但现在它只添加拥有一个或多 个 ControlsToUpdate 数组中控件的窗体,因此只有那些含有特定控件的窗体在更新集合中。它使我可以从每个窗体中调用该函数。如果我决定以后添加某个特定的控件,它将会被自动添加到窗体列表。我只需对窗体代码做细小的改动便可以实现。
  这个模块还包含 UpdateControlsOnAllForms 过程,它执行更新。代替上一个方法中使用的一个应用程序级变量,我现在使用主窗体的概念。因此我可以将那个窗体的值拷贝到集合中的所有其它窗体。UpdateControlsOnAllForms 其实就是一组简单的 For...Nexts 循环遍历某个窗体的所有控件,找到需要更新的控体,并更新它们。
  为了在我的窗体中实现这一功能,我在窗体的 Load 事件中加入了这一行代码:
AddFormToUpdate(Me) 
  另外一种可选的方法,我可以将它添加到构造函数。这一行代码将把当前窗体实例添加到集合进行更新。
  现在让我们考察单个事件过程:
Private Sub txt_Leave(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles txtAddress.Leave, _ txtCustomer.Leave, txtName.Leave UpdateControlsOnAllForms(Me) End Sub 
  这段代码将我想要同步的所有三个控件 (txtAddress、txtCustomer 和 txtName)的 Leave 事件捆绑到一个事件句柄上。这时我可以添加一行代码 来调用 UpdateControlsOnAllForms。Me 被传递到该过程调用,从而导致其它窗体与该窗体同步。

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:vb / C# 中报表套打的轻松实现

下一篇:VB之Win32 API编程--判断本地或远程文件是否存在的简易方法