隨著桌面系統的推出利用鼠標的拖放(Drag and Drop)操作由於其簡單直接受到了越來越多的讀者的歡迎為迎合這種趨勢越來越多程序員在自己的程序中使用了拖放操作拖放操作方便了程序的使用者但由於拖放操作在程序中的設計工作比較還有點麻煩甚至是一個難點許多程序員對其都有點心有余悸本文就結合微軟公司最新的Net程序開發語言C#來全面介紹一下在C#中是如何處理拖放操作的
在本文中我們是通過二個代表組件也是在拖放操作中經常使用到的二個組件TreeView組件和ListView組件之間互相進行拖放操作來說明此類問題的在進行拖放操作之前必須要對進行拖放操作的組件的AllowDrop屬性值設定為True因為此屬性是確定組件是否可以進行拖放操作的
一.本文中介紹的程序的設計和運行的軟件環境
()微軟公司視窗服務器版
()Net FrameWork SDK Beta
二.由TreeView組件到ListView組件的拖放操作
要完成此次的拖放操作必須處理好三種事件ItemDragDragEnterDragDrop其中只有第一種事件是在源組件中觸發的另外二種事件是在目標組件中觸發的其中當用戶拖動組件觸發ItemDrag事件當拖動數據進入目標組件區域觸發DragEnter事件當用戶在目標組件區域放置拖動的數據觸發DragDrop事件下面就根據拖放操作的操作順序來詳細介紹
()開始拖(Drag)操作
通過DoDragDrop方法拉開了拖放操作的第一步DoDragDrop方法的語法為
DoDragDrop ( object data DragDropEffects allowedEffects ) ;
其中第二個參數來是說明此次拖放操作最後所要實現的效果因為拖放操作有時實現的效果是把源組件中的內容拖到目標組件中這種效果就是Move有時拖放的效果是在目標組件中加入拖動的數據對源組件的內容是沒有什麼影響的這種效果就是Copy當然無論是Move還是Copy這都要通過具體的編程來實現設定這些效果只是告訴操作系統你進行拖放操作的類型從而為拖放操作設定特定的圖標此例中實現開始拖放操作的具體實現代碼如下
private void treeView_ItemDrag ( object sender ItemDragEventArgs e )
{
string strItem = eItemToString ( ) ;
//開始進行Drag操作
DoDragDrop ( strItem DragDropEffectsCopy | DragDropEffectsMove ) ;
}
在上面代碼中我們定義的拖放數據類型是字符串其實拖放的數據類型可以是很多種的你可以通過修改DoDragDrop方法的第一個參數來設定你所要拖放數據類型譬如位圖或者其他什麼
()目標組件允許進行拖放操作
既然你已經開始進行拖放操作你還必須告訴你要拖放到的目標組件要接受你所拖放的數據DragEnter事件正好可以處理在下列的代碼中我們是通過判斷拖放數據類型來確定是否接受拖放如果是字符串則可以否則則不行具體代碼如下
private void listView_DragEnter ( object sender DragEventArgs e )
{
//判斷是否目前拖動的數據是字符串如果是則拖動符串對目的組件進行拷貝if ( eDataGetDataPresent ( DataFormatsText ) ) eEffect = DragDropEffectsMove ;
else
eEffect = DragDropEffectsNone ;
}
()獲得拖放的字符串在目標組件中加入相應的內容
此步的處理過程是十分明確的要分成二步來進行首先要得到拖放的字符串其次是在目標組件中加入以此字符串為標題的項目當然還要在相應的位置了下面就是實現這二步操作的具體代碼
private void listView_DragDrop ( object sender DragEventArgs e )
{
string dummy = temp ;
//獲得進行Drag操作中拖動的字符串
string s = ( string ) eDataGetData ( dummyGetType ( ) ) ;
s = sSubstring ( sIndexOf ( : ) + )Trim ( ) ;
PositionX = eX ;
PositionY = eY ;
Position = listViewPointToClient ( Position ) ;
//在目標組件中加入以此字符串為標題的項目
listViewItemsAdd ( new ListViewItem ( s ) ) ;
}
此致通過對這三個事件的編程已經完成了由TreeView組件到ListView組件的拖放操作
三.由ListView組件到TreeView組件的拖放操作
由ListView組件到TreeView組件的拖放操作和從TreeView組件到ListView組件相類似也是通過ItemDragDragEnterDragDrop三個事件來處理的具體如下
()開始拖(Drag)操作
這和前者沒有什麼實質上的區別只是在此次的拖放操作開始之前多加入了一些邏輯判斷讓程序更穩健的允許實現的代碼如下
private void listView_ItemDrag ( object sender ItemDragEventArgs e )
{
//判斷是否是鼠標右鍵按動
if ( eButton == MouseButtonsRight ) return ;
int nTotalSelected = listViewSelectedIndicesCount ;
//判斷組件中是否存在項目
if ( nTotalSelected <= ) return ;
IEnumerator selCol = listViewSelectedItemsGetEnumerator ( ) ;
selColMoveNext ( ) ;
ListViewItem lvi = ( ListViewItem )selColCurrent ;
string mDir = ;
for ( int i = ; i < lviSubItemsCount ; i++ ) mDir += lviSubItems[ i ]Text + ;
string str = mDirSubstring ( mDirLength ) ;
if ( str == ) return ;
//對組件中的字符串開始拖放操作
listViewDoDragDrop ( str DragDropEffectsCopy | DragDropEffectsMove ) ;
}
()目標組件允許進行拖放操作
這一步是進行拖放操作最為一致的除非你所要進行拖放的數據類型有改變否則沒有必要對源代碼進行什麼修改具體如下
private void treeView_DragEnter ( object sender DragEventArgs e )
{
//判斷是否目前拖動的數據是字符串如果是則拖動符串對目的組件進行拷貝if ( eDataGetDataPresent ( DataFormatsText ) ) eEffect = DragDropEffectsCopy ;
else
eEffect = DragDropEffectsNone ;
}
()獲得拖放的字符串在目標組件中加入相應的內容
對於進行拖放操作的不同組件獲得其拖放的數據的實現方法是不一樣的在本步驟中也不例外但總歸大同小異掌握程序設計的步驟和要點加上探索研究的精神這個問題應該能夠解決下面是實現此步驟的程序代碼
private void treeView_DragDrop ( object sender DragEventArgs e )
{
//獲得進行Drag操作中拖動的字符串
string dummy = temp ;
string s = ( string ) eDataGetData ( dummyGetType ( ) ) ;
s = sSubstring ( sIndexOf ( : ) + )Trim ( ) ;
PositionX = eX ;
PositionY = eY ;
Position = treeViewPointToClient ( Position ) ;
TreeNode DropNode = thistreeViewGetNodeAt ( Position ) ;
//在目標組件中加入以此字符串為標題的項目
if ( DropNode != null )
{
TreeNode DragNode = new TreeNode ( s ) ;
treeViewNodesInsert ( DropNodeIndex+ DragNode ) ;
}
}
四. 二個組件進行拖放操作的完整源程序代碼(dragdropcs)
在掌握了上面的這些步驟過以後可以得到這二個組件相互進行拖放操作的完整代碼和編譯後程序的運行界面如下
圖二個組件相互進行拖放的程序運行界面
dragdropcs的代碼如下
using System ;
using SystemDrawing ;
using SystemCollections ;
using SystemComponentModel ;
using SystemWindowsForms ;
using SystemData ;
//導入程序中使用的命名空間
public class Form : Form
{
private TreeView treeView ;
private Point Position = new Point( ) ;
// bool lv_mdown = false ;
private ListView listView ;
private SystemComponentModelContainer components = null ;
public Form ( )
{
InitializeComponent ( ) ;
//初始化窗體中的各個組件
}
//清除程序中使用到的各種資源
protected override void Dispose ( bool disposing )
{
if ( disposing )
{
if ( components != null )
{
componentsDispose ( ) ;
}
}
baseDispose ( disposing ) ;
}
private void InitializeComponent ( )
{
ListViewItem listViewItem = new ListViewItem ( Item ) ;
ListViewItem listViewItem = new ListViewItem ( Item ) ;
treeView = new TreeView ( ) ;
listView = new ListView ( ) ;
SuspendLayout ( ) ;
//此屬性必須設定為真這樣才能進行拖放操作treeViewAllowDrop = true ;
treeViewImageIndex = ;
treeViewLocation = new Point ( ) ;
treeViewName = treeView ;
//在TreeView組件中加入初始化的節點
treeViewNodesAdd ( new TreeNode ( 節點 ) );
treeViewNodesAdd ( new TreeNode ( 節點 ) );
treeViewSelectedImageIndex = ;
treeViewSize = new Size ( ) ;
treeViewTabIndex = ;
treeViewDragEnter += new DragEventHandler ( treeView_DragEnter ) ;
treeViewItemDrag += new ItemDragEventHandler ( treeView_ItemDrag ) ;
treeViewDragDrop += new DragEventHandler ( treeView_DragDrop ) ;
//此屬性必須設定為真這樣才能進行拖放操作listViewAllowDrop = true ;
//在ListView組件中加入項目
listViewItemsAdd ( listViewItem ) ;
listViewItemsAdd ( listViewItem ) ;
listViewLocation = new Point ( ) ;
listViewName = listView ;
listViewSize = new Size ( ) ;
listViewTabIndex = ;
listViewView = ViewList ;
listViewDragDrop += new DragEventHandler ( listView_DragDrop ) ;
listViewDragEnter += new DragEventHandler ( listView_DragEnter ) ;
listViewItemDrag += new ItemDragEventHandler ( listView_ItemDrag ) ;
AutoScaleBaseSize = new Size ( ) ;
ClientSize = new Size ( ) ;
ControlsAdd ( listView );
ControlsAdd ( treeView );
thisMaximizeBox = false ;
thisMinimizeBox = false ;
thisName = Form ;
thisText = 全面掌握C#中的拖放操作 ;
thisResumeLayout ( false ) ;
}
static void Main ( )
{
ApplicationRun ( new Form ( ) ) ;
}
private void treeView_ItemDrag ( object sender ItemDragEventArgs e )
{
string strItem = eItemToString ( ) ;
//開始進行Drag操作
DoDragDrop ( strItem DragDropEffectsCopy | DragDropEffectsMove ) ;
}
private void listView_DragEnter ( object sender DragEventArgs e )
{
//判斷是否目前拖動的數據是字符串如果是則拖動符串對目的組件進行拷貝if ( eDataGetDataPresent ( DataFormatsText ) ) eEffect = DragDropEffectsMove ;
else
eEffect = DragDropEffectsNone ;
}
private void listView_DragDrop ( object sender DragEventArgs e )
{
string dummy = temp ;
//獲得進行Drag操作中拖動的字符串
string s = ( string ) eDataGetData ( dummyGetType ( ) ) ;
s = sSubstring ( sIndexOf ( : ) + )Trim ( ) ;
PositionX = eX ;
PositionY = eY ;
Position = listViewPointToClient ( Position ) ;
//在目標組件中加入以此字符串為標題的項目
listViewItemsAdd ( new ListViewItem ( s ) ) ;
}
private void listView_ItemDrag ( object sender ItemDragEventArgs e )
{
//判斷是否是鼠標右鍵按動
if ( eButton == MouseButtonsRight ) return ;
int nTotalSelected = listViewSelectedIndicesCount ;
//判斷組件中是否存在項目
if ( nTotalSelected <= ) return ;
IEnumerator selCol = listViewSelectedItemsGetEnumerator ( ) ;
selColMoveNext ( ) ;
ListViewItem lvi = ( ListViewItem )selColCurrent ;
string mDir = ;
for ( int i = ; i < lviSubItemsCount ; i++ ) mDir += lviSubItems[ i ]Text + ;
string str = mDirSubstring ( mDirLength ) ;
if ( str == ) return ;
//對組件中的字符串開始拖放操作
listViewDoDragDrop ( str DragDropEffectsCopy | DragDropEffectsMove ) ;
}
private void treeView_DragEnter ( object sender DragEventArgs e )
{
//判斷是否目前拖動的數據是字符串如果是則拖動符串對目的組件進行拷貝if ( eDataGetDataPresent ( DataFormatsText ) ) eEffect = DragDropEffectsCopy ;
else
eEffect = DragDropEffectsNone ;
}
private void treeView_DragDrop ( object sender DragEventArgs e )
{
//獲得進行Drag操作中拖動的字符串
string dummy = temp ;
string s = ( string ) eDataGetData ( dummyGetType ( ) ) ;
s = sSubstring ( sIndexOf ( : ) + )Trim ( ) ;
PositionX = eX ;
PositionY = eY ;
Position = treeViewPointToClient ( Position ) ;
TreeNode DropNode = thistreeViewGetNodeAt ( Position ) ;
//在目標組件中加入以此字符串為標題的項目
if ( DropNode != null )
{
TreeNode DragNode = new TreeNode ( s ) ;
treeViewNodesInsert ( DropNodeIndex+ DragNode ) ;
}
}
}
五.其他組件的拖放操作
本文雖然對TreeView組件和ListView組件之間的拖放操作進行了詳細的介紹對於其他的可以用於拖放操作的組件很多組件的拖放操作的實現方法都和這二種差不多但也有一些組件有一些區別譬如ListBox組件等在進行拖放操作的時候他就沒有本文介紹的ItemDrag事件那這怎麼辦我們是通過一個變通的方法來實現的具體是通過MouseMove事件和MouseDown事件來代替ItemDrag事件其中MouseMove事件主要是起到觸發拖放操作的作用MouseDown事件主要是起著判斷此次拖放操作是否已經完成的作用對於ListBox組件拖放操作的其他步驟也和上面介紹的二個組件沒有什麼太大區別由於篇幅的關系ListBox組件和其他不存在ItemDrag事件的組件的拖放操作這裡就不一一介紹了相信大家能夠搞定
六.總結
對於大多數組件來說掌握了ItemDragDragEnterDragDrop三個事件的解決辦法也就掌握了組件間的拖放操作當然還有一些例外的組件但總而言之拖放操作的實現步驟都是一樣的解決的思路也是大致一致的由於拖放操作的自身的優點對於程序員來說盡快掌握是十分必要的希望本文介紹的內容能夠令你滿意
From:http://tw.wingwit.com/Article/program/net/201311/13420.html