這是一個有趣的問題
我保證某些聰明的編程好手會建議我使用委托
在這種事情發生之前
讓我們 先探究一下這個問題的幾種解決方案
假定我有兩個窗體
每個窗體都有兩個 textbox 控件
txt
stData 和 txt
ndData
我怎樣才能保持這兩個窗體中的控件同步呢?對於我們討論的問題來說
有兩個或十個窗體都不重要
問題是相同的
第一個辦法相對簡單
事實上
它甚至比我們直接使用委托更為簡單
我想委托有時會給人用牛刀殺雞的感覺
首先
我建立一個類它包含我希望與應用程序中的所有窗體共享的屬性(參見 Figure
)
例如
MyData 和 MoreData 擁有每個窗體都能顯示的數據
我將很快回到這個類來
第二
正如我早先提到的我用相同的控件(txt
stData 和 txt
ndData)建立了兩個窗體
你可以參考 Figure
的布局
兩個窗體都有完全相同的數據
並且我將很快解釋為什麼
下面
我建立一個名為 modGeneral 的模塊並加入下面一行代碼
Friend DataStuff As DataClass
這一行代碼為我的新類 DataClass 創建了一個友元變量
使你可以完全訪問程序集
對這個簡單例子來說
也就是指完整的應用程序
然後我添加了下面的代碼到 Form
的 Load 事件
DataStuff = New DataClass
Me
txt
stData
DataBindings
Add(
Text
DataStuff
MyData
)
Me
txt
ndData
DataBindings
Add(
Text
DataStuff
MoreData
)
第一行建立一個 DataClass 新實例
下面兩行代碼將數據綁定到 textbox 控件
對這個窗體而言
就這麼些操作!
現在
你怎樣讓它們與 Form
和其它窗體上的數據同步呢?將下面兩行加入到 Form
的窗體load 事件中去
Me
txt
stData
DataBindings
Add(
Text
DataStuff
MyData
)
Me
txt
ndData
DataBindings
Add(
Text
DataStuff
Moredata
)
這個方法容易確保所有窗體上的幾乎任何類型的數據處於同步狀態
你可以簡單地將控件綁定到某個類的相同實例上
這就行了
現在來看另一個方法
我創建了一個名為 frmBase 的新窗體
這時我在上面放一個 textbox (txtNextData)和 label
我想 讓應用程序的每個窗體都共享這個 textbox 和 label
並且我希望它們互相之間保持同步
於是我重建這個工程
通過從新的 frmBase 中的繼承
我創建了 Form
和Form
因此它們繼承了所有新的控件
但是我怎樣能保持這些控件同步呢?這時必須寫一點代碼去達到此效果
這些代碼在單個的類中
通過簡單地調用一個函數而被復用
Figure
中的代碼展示了這個稱為 modGeneral 模塊
它的第一個任務是定義兩個變量
MyForms 和 localNextData
MyForms 是一個 集合
它將包含我想要同步的窗體列表
localNextData變量將儲存所有我想要在窗體裡顯示的數據
注意這些變量可以駐留於某個類中而不是某個模塊裡
AddForm 過程來自 modGeneral
帶一個窗體實例參數
並將其加入 MyForms 集合中
我將在UpdateControlsNextData 過程中使用這個 集合以決定哪些窗體要更新
AddForm 也調用UpdateControlsNextData 來確保一個新窗體是用正確的數據更新的
modGeneral 中的其它代碼是 NextData 屬性
這些屬性的 set 存取器更新 localNextData 並也調用 UpdateControlsNextData 去同步所有窗體
這時所有我需要做的是 在想要改變它時設置 NextData
通過調用 UpdateControlsNextData
所有窗體將被更新
第三個方法是定制鏈接
它是第二個方法的精華版
我創建它以獲得多一些窗體控件處理的靈活性
例如
我只想跟蹤和處理某些窗體
這些窗體包含必須同步的控件
這個方法 還可以讓我自己定義擬同步的控件
並且只處理這些控件的窗體
我為這個辦法添加了另一個模塊 (modGeneralv
)
如 Figure
所示
該模塊包括一個集合(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 被傳遞到該過程調用
從而導致其它窗體與該窗體同步
現在我有三個版本的代碼
它們都可以同步窗體中控件
因此我可以進行選擇
我可能已經使用了自定義事件
在 DataClass 中定義某個事件並讓每個窗體都預訂它
然後當這個事件觸發時
這些窗體可以從每個事件句柄中獲取新的數據並設置適當的控件
但是這樣做所需的代碼量一點也不會比第一種方法中將控件綁定到類來得少
我可以構建單個實現更新的過程
並將該過程放到某個模塊中
我需要向該過程傳遞窗體實例來實現更新
我可以用類中的某個事件句柄觸發這個過程
此過程看起來就像這樣
Sub UpdateControls(ByVal ThisForm As frmBase)
With ThisForm
txtNextData
Text = localNextData
End With
End Sub
ThisForm 參數被定義為 frmBase 類型
以便它可以訪問 IntelliSense 並獲得窗體的自定義屬性
簡單地將它寫成 Form 將無法顯示 frmBase 中的屬性及其派生窗體
另一選擇是使用委托
當然
委托可以讓我將委托調用重定向到每個窗體的方法上
如果我使用多播機制
那麼我可以讓每個窗體都處理該事件並更新相應的控件
用委托建立這樣的功能聽起來確實簡單
但 對我來說它更麻煩且沒有實踐價值
此外
與第三個方法中的 For
Next 循環嵌套相比
這個代碼並不難理解
畢竟
一個應用程序花費最大的部分仍然是它的維護
From:http://tw.wingwit.com/Article/program/net/201311/11593.html