一、引言
我們在平時項(xiàng)目開發(fā)中經(jīng)常會遇到這種情況,開發(fā)需要一些特定的功能控件,而現(xiàn)有的控件又只能滿足部分的要求,這個時候一般采利用現(xiàn)有控件功能,對其進(jìn)行擴(kuò)展以滿足項(xiàng)目需要。但如何在沒有源碼的情況下擴(kuò)展控件功能,并且可以用和原來一致的方法調(diào)用擴(kuò)展控件就需要一點(diǎn)技巧了。借助VS2005的強(qiáng)大功能和面向?qū)ο缶幊痰睦^承思想可以很容易實(shí)現(xiàn)這個需求,而且具體實(shí)現(xiàn)過程就如同我們有這些控件的源碼一樣。
二、實(shí)例
在大多數(shù)基于數(shù)據(jù)庫應(yīng)用的開發(fā)中DataGridView控件使用很多,DataGridView為微軟自家產(chǎn)品,可以方便地綁定到數(shù)據(jù)庫表以及泛型容器List,但其有個缺點(diǎn)就是不支持表格數(shù)據(jù)的粘貼功能,使得對數(shù)據(jù)進(jìn)行批量修改很不方便。有人將ContextMenuStrip關(guān)聯(lián)到DataGridView上,通過右鍵菜單實(shí)現(xiàn)了DataGridView的粘貼、復(fù)制等功能,但其有個缺點(diǎn)就是在需要這些擴(kuò)展功能的地方要寫大量相同的代碼。如何采用更加優(yōu)雅的方式實(shí)現(xiàn)這個功能,使右鍵菜單就像DataGridView原生的功能一樣,首先想到的就是創(chuàng)建一個包含DataGridView的擴(kuò)展控件,使之響應(yīng)ContextMenuStrip定義的菜單命令,而我們只要從工具箱拖一個DataGridView控件到窗體,修改其類型為我們前面創(chuàng)建的自定義控件類型就能滿足要求。
由于代碼以經(jīng)包含在下文中,且本文的主要目以介紹方法為主,不再另附工程實(shí)例,見諒。 實(shí)例具體實(shí)現(xiàn)如下:
1,啟動VB2005新建類庫項(xiàng)目DataGridViewExt(C#等其它.NET語言實(shí)現(xiàn)方法一樣,這里不另行介紹,見諒)。
[attach]691254[/attach]
2,添加組件類DataGridViewExt。
[attach]691255[/attach]
3,添加控件ContextMenuStrip,然后給ContextMenuStrip1添加兩個子菜單menu_copy和menu_paste,并把相應(yīng)的text屬性設(shè)為復(fù)制和粘貼,使得右鍵菜單直觀明了。
[attach]691256[/attach]
4,此時會發(fā)現(xiàn)VB2005提示有很多錯誤,這是因?yàn)楣こ倘鄙賹ystem.Drawing引用,添加引用System.Drawing后錯誤消失
[attach]691257[/attach]
5,現(xiàn)在我們讓DataGridViewExt從DataGridView繼承下來,在DataGridViewExt.design.vb文件中將
InheritsSystem.ComponentModel.Component
改為:
InheritsSystem.ComponentModel.Component
并且在控件new()過程中添加
Me.ContextMenuStrip = ContextMenuStrip1
Me.ClipboardCopyMode = System.Windows.Forms.DataGridViewClipboardCopyMode.EnableWithAutoHeaderText
6,添加菜單menu_copy和menu_paste的單擊事件處理;對復(fù)制功能我們可以直接調(diào)用系統(tǒng)的剪切板功能來實(shí)現(xiàn),而對粘貼功能實(shí)現(xiàn)則要稍微麻煩一點(diǎn),需要對各數(shù)據(jù)列的分割符進(jìn)行判讀處理。具體處理方式是先根據(jù)回車換行標(biāo)志,將數(shù)據(jù)分割成若干行,再對每行的數(shù)據(jù)按Tab標(biāo)記分割為若干列,這樣就形成了一個二維的表格數(shù)據(jù),從而可以支持復(fù)制到DataGridView控件。經(jīng)過測試,以下介紹的分割方法能夠支持從Excel,記事本等程序的數(shù)據(jù)與DataGridView相互復(fù)制粘貼。
Private Sub menu_copy_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles menu_copy.Click
'清除剪切板原有內(nèi)容,將表格數(shù)據(jù)復(fù)制到剪切板
System.Windows.Forms.Clipboard.Clear()
System.Windows.Forms.Clipboard.SetDataObject(Me.GetClipboardContent())
End Sub
Private Sub menu_paste_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles menu_paste.Click
Dim i, j As Integer
Dim pRow, pCol As Integer
Dim selectedCellCount As Integer
Dim startRow, startCol, endRow, endCol As Integer
Dim pasteText, strline, strVal As String
Dim strlines, vals As String()
Dim pasteData(,) As String
Dim flag As Boolean = False
' 當(dāng)前單元格是否選擇的判斷
If Me.CurrentCell Is Nothing Then
Return
End If
Dim insertRowIndex As Integer = Me.CurrentCell.RowIndex
' 獲取DataGridView選擇區(qū)域,并計算要復(fù)制的行列開始、結(jié)束位置
startRow = 9999
startCol = 9999
endRow = 0
endCol = 0
selectedCellCount = Me.GetCellCount(DataGridViewElementStates.Selected)
For i = 0 To selectedCellCount - 1
startRow = Math.Min(Me.SelectedCells(i).RowIndex, startRow)
startCol = Math.Min(Me.SelectedCells(i).ColumnIndex, startCol)
endRow = Math.Max(Me.SelectedCells(i).RowIndex, endRow)
endCol = Math.Max(Me.SelectedCells(i).ColumnIndex, endCol)
Next
' 獲取剪切板的內(nèi)容,并按行分割
pasteText = Clipboard.GetText()
If String.IsNullOrEmpty(pasteText) Then
Return
End If
pasteText = pasteText.Replace(vbCrLf, vbLf)
ReDim strlines(0)
strlines = pasteText.Split(vbLf)
pRow = strlines.Length '行數(shù)
pCol = 0
For Each strline In strlines
ReDim vals(0)