圖8.16在兩個列表間來回拖放項(xiàng)目
圖8.16所示是程序范例CH8_DemoForm014.vb的運(yùn)行界面。顯然,您可以在兩個列表間來回拖放一個或多個文件來移動項(xiàng)目。本程序范例的設(shè)計(jì)重點(diǎn)說明如下:- 由于兩個列表的ListView控件都可以作為置放目標(biāo),因此務(wù)必將這兩個ListView控件的AllowDrop屬性設(shè)定成True。
- 請將兩個ListView控件的MultiSelect屬性設(shè)定成True。
- 請將兩個ListView控件的FullRowSelect屬性設(shè)定成True。
- 以下是程序范例CH8_DemoForm014.vb的程序代碼內(nèi)容。在Load事件處理函數(shù)中所調(diào)用的 PopulateListView()程序主要是用來初始化兩個ListView控件:
ByVal e As System.EventArgs)Handles MyBase.Load
Me.PopulateListView()
End Sub
Private Sub ListView_ItemDrag(ByVal sender As Object, _
ByVal e As System.Windows.Forms.ItemDragEventArgs)_
Handles ListView1.ItemDrag, ListView2.ItemDrag
Dim myItem As ListViewItem
Dim myItems(CType(sender, ListView).SelectedItems.Count-1)_
As ListViewItem
Dim i As Integer=0
' 循環(huán)處理拖放源的SelectedItems集合。
For Each myItem In CType(sender, ListView).SelectedItems
' 將ListViewItem添加到ListViewItems的數(shù)組中。
myItems(i)=myItem
i=i+1
Next
' 創(chuàng)建一個DataObject對象來含有ListViewItem的數(shù)組。
CType(sender, ListView).DoDragDrop(New _
DataObject(_
"System.Windows.Forms.ListViewItem()", myItems), _
DragDropEffects.Move)
End Sub
Private Sub ListView_DragEnter(ByVal sender As Object, _
ByVal e As System.Windows.Forms.DragEventArgs)_
Handles ListView1.DragEnter, ListView2.DragEnter
' 檢查自定義的DataFormat ListViewItem數(shù)組。
If e.Data.GetDataPresent(_
"System.Windows.Forms.ListViewItem()")Then
e.Effect=DragDropEffects.Move
Else
e.Effect=DragDropEffects.None
End If
End Sub
Private Sub ListView_DragDrop(ByVal sender As Object, _
ByVal e As System.Windows.Forms.DragEventArgs)_
Handles ListView1.DragDrop, ListView2.DragDrop
Dim myItem As ListViewItem
Dim myItems()As ListViewItem=_
CType(_
e.Data.GetData(_
"System.Windows.Forms.ListViewItem()"), _
ListViewItem())
Dim i As Integer=0
For Each myItem In myItems
' 將項(xiàng)目添加到目標(biāo)列表中。
Dim item As New ListViewItem(myItems(i).Text)
item.SubItems.Add(myItems(i).SubItems(1).Text)
CType(sender, ListView).Items.Add(item)
' 從源列表刪除項(xiàng)目。
If sender Is ListView1 Then
ListView2.Items.Remove(ListView2.SelectedItems.Item(0))
Else
ListView1.Items.Remove(ListView1.SelectedItems.Item(0))
End If
i=i+1
Next
End Sub
您或許會覺得奇怪,為什么不使用ListBox控件而要使用ListView控件。最主要的理由是,ListBox控件并不支持拖曳多個項(xiàng)目,單擊列表會使得多重選擇失效。
ListView與TreeView控件都擁有一個ItemDrag事件來促進(jìn)拖曳。在本范例中,我們使用單一個ItemDrag事件處理函數(shù)來處理兩個ListView控件的ItemDrag事件。其中的sender參數(shù)代表初始化拖拽的控件。
由于DataFormats類的成員并不包括ListViewItem類型,所以數(shù)據(jù)必須被當(dāng)作一個系統(tǒng)Type來傳遞。ItemDrag事件處理函數(shù)的程序代碼會創(chuàng)建一個類型為ListViewItem的數(shù)組并循環(huán)處理SelectedItems集合以便填入數(shù)組。在DoDragDrop方法中,一個新的DataObject對象會被創(chuàng)建并以數(shù)組來填入。您可以使用相同的技巧來拖放任何的系統(tǒng)Type。
在DragDrop事件處理函數(shù)中,我們會將DataObject對象中的數(shù)組復(fù)制到一個新的ListViewItem數(shù)組中,而且每一個ListViewItem會被添加到目標(biāo)ListView控件的Items集合中。
在兩個TreeView之間來回拖放節(jié)點(diǎn)
圖8.17如何在TreeView之間來回拖放節(jié)點(diǎn)
圖8.18如何在TreeView之間來回拖放節(jié)點(diǎn)圖8.17與8.18所示是程序范例CH8_DemoForm015.vb的運(yùn)行界面。顯然,您可以在兩個TreeView控件間來回拖放一個節(jié)點(diǎn)(移動或復(fù)制)。本程序范例的程序代碼如下所列:
' 聲明一個常量以便偵測在拖曳期間CTRL鍵是否被按下。
Const CtrlMask As Byte=8
' 處理兩個TreeView控件的ItemDrag事件。
Private Sub TreeView_ItemDrag(ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.ItemDragEventArgs)_
Handles tvwRight.ItemDrag, tvwLeft.ItemDrag
If e.Button=Windows.Forms.MouseButtons.Left Then
' 初始化拖放操作。
DoDragDrop(e.Item, _
DragDropEffects.Move Or DragDropEffects.Copy)
End If
End Sub
' 處理兩個TreeView控件的DragDrop事件。
Private Sub TreeView_DragDrop(ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.DragEventArgs)_
Handles tvwLeft.DragDrop, tvwRight.DragDrop
' 此變量用來持有被用戶所拖曳的節(jié)點(diǎn)。
Dim OriginationNode As TreeNode=_
CType(_
e.Data.GetData(_
"System.Windows.Forms.TreeNode"), TreeNode)
' 為一個TreeView控件調(diào)用GetDataPresent方法與替
' 一個文字或圖像的方式一點(diǎn)不同,原因是TreeNode并不是
' DataFormats類的一個成員。也就是說,它不是一個預(yù)先
' 定義的類型。諸如此種狀況,您必須使用能夠接受一個字符串
' 作為類型的重載版本。
If e.Data.GetDataPresent(_
"System.Windows.Forms.TreeNode", False)Then
Dim pt As Point
Dim DestinationNode As TreeNode
' 取得鼠標(biāo)指針?biāo)谖恢玫墓ぷ鲄^(qū)坐標(biāo)(Client Coordinate)。
pt=CType(sender, TreeView).PointToClient(_
New Point(e.X, e.Y))
' 選取鼠標(biāo)指針?biāo)谖恢弥碌墓?jié)點(diǎn)。
DestinationNode=_
CType(sender, TreeView).GetNodeAt(pt)
' 此處的If語句用來確保當(dāng)用戶在他們嘗試
' 去拖曳之節(jié)點(diǎn)的上方不小心放開鼠標(biāo)按鍵的話,
' 不會失去節(jié)點(diǎn)。如果您沒有去檢查目標(biāo)節(jié)點(diǎn)是否
' 就是來源節(jié)點(diǎn),將會使得該節(jié)點(diǎn)消失掉。
If DestinationNode.TreeView _
IsNot OriginationNode.TreeView Then
DestinationNode.Nodes.Add(_
CType(OriginationNode.Clone, TreeNode))
' 當(dāng)添加一個新的節(jié)點(diǎn)時展開父節(jié)點(diǎn),如此才會
' 清楚地呈現(xiàn)出拖放操作的結(jié)果。如果沒有這樣
' 做的話,將會顯示一個+號。
DestinationNode.Expand()
' 如果CTRL鍵沒有被按下,就將原來的節(jié)點(diǎn)刪除
' 以便實(shí)現(xiàn)移動節(jié)點(diǎn)的拖放操作。
If(e.KeyState And CtrlMask)<> CtrlMask Then
OriginationNode.Remove()
End If
End If
End If
End Sub
' 處理兩個TreeView控件的DragEnter事件。
Private Sub TreeView_DragEnter(ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.DragEventArgs)_
Handles tvwRight.DragEnter, tvwLeft.DragEnter
' 檢查被拖曳的數(shù)據(jù)的類型是否適用于目標(biāo)控件。
' 如果不適用,則拒絕置放。
If(e.Data.GetDataPresent(_
"System.Windows.Forms.TreeNode"))Then
' 如果在拖曳期間按著CTRL鍵,則執(zhí)行復(fù)制操作;
' 反之,則執(zhí)行移動操作。
If(e.KeyState And CtrlMask)=CtrlMask Then
e.Effect=DragDropEffects.Copy
Else
e.Effect=DragDropEffects.Move
End If
Else
e.Effect=DragDropEffects.None
End If
End Sub