Windows本身就支持大量的拖放操作,这样就创造了很好的用户体验。看了同类的一些软件,也在一些地方支持拖放操作,的确让使用软件变得比较方便,所以我们也打算在软件中尽可能的支持拖放操作,毕竟对于使用软件的人来说,越是直观的操作越好。
本来说来,在目前的阶段,不太适合进入到这种技术细节中去。但是目前由于不可抗拒的因素,让项目有所波折(只是暂时的问题,一切都会好起来的!),个人也想换换思维便研究起了拖放操作,对于以后实施也会有一定的借鉴意义。在设计界面上可以少走一些弯路。恩,废话少说,介绍一下拖放操作的实现先,也算是让自己再深入一次:
1、首先,在进行拖放操作之前,必须要对进行拖放操作的组件的"AllowDrop"属性值设定为"True",因为此属性是确定组件是否可以进行拖放操作的。 不管是拖放操作的源控件还是目的控件的设置都是这样。
2、然后要完成一次的拖放操作,必须处理好三种事件:"ItemDrag"、"DragEnter"、"DragDrop"、"DragOver"、"DragLeave"。其中只有第一种事件是在源组件中触发的,另外四种事件是在目标组件中触发的(绝大多数控件能响应这几个事件)。其中当用户拖动组件触发"ItemDrag"事件;当拖动数据进入目标组件区域触发"DragEnter"事件;当用户在目标组件区域放置拖动的数据触发"DragDrop"事件,当用户的拖放光标进入目标区域触发"DragOver",当用户的拖放光标离开拖放区域时触发"DragLeave" 。下面就根据拖放操作的操作顺序来详细介绍:
(1) 开始"拖"(Drag)操作--触发"ItemDrag"事件:
大多数控件都不具有ItemDrag的事件的定义,像TextBox就没有。发现两个有这个定义的控件是ListView和TreeView。
看代码如下:
private void treeView1_ItemDrag(object sender,ItemDragEventArgs e)
{
string strItem=e.Item.ToString();
//开始进行"Drag"操作
DragDropEffects dde=DoDragDrop(strItem,DragDropEffects.Copy|DragDropEffects.Move);
}
在这里可以看见一个方法do
DragDrop ( object data , DragDropEffects allowedEffects ),这个方法启动一个拖放操作,并且方法阻塞在这里等待拖放操作的返回,在DoDragDrop之后可以放置对拖放操作结果的处理代码,对于跨窗体跨应用程序的拖放操作是非常有意义的。
具体的信息可以查看 http://www.dbo.cn/Resource/msdn/cpref/frlrfsystemwindowsformscontrolclassdodragdroptopic.htm 。
do
DragDrop 方法有两个参数,第一个参数是要在拖放操作传递的数据,你可以放入各种数据类型,第二个参数来是说明此次拖放操作最后所要实现的效果,因为拖放操作有时实现的效果是把源组件中的内容"拖"到目标组件中,这种效果就是"Move";有时拖放的效果是在目标组件中加入拖动的数据,对源组件的内容是没有什么影响的,这种效果就是"Copy"。当然无论是"Move"还是"Copy",这都要通过具体的编程来实现,设定这些效果只是告诉操作系统,你进行拖放操作的类型,从而为拖放操作设定特定的图标。
do
DragDrop 返回的值也是 DragDropEffects 表示拖放操作所达成的效果。
值得注意的还有,上面的代码对于鼠标左右键拖放都会响应,如果只想支持左键拖放需要加入对鼠标的判断。
//判断是否是鼠标右键按动
if ( e.Button == MouseButtons.Right ) return;
(2) 让目标组件允许进行拖放操作:
上面提到了你可以将某种类型的数据,拖放到目标组件上,但是目标组件可能只能处理某种类型的数据,比如一个MP3播放软件,不允许将一个AVI的文件拖放到播放列表中,因为它处理不了。所以在拖放操作进入目标区域时候,需要对该拖放操作进行判断,主要是判断拖放中带有的数据类型。
"DragEnter"事件正好可以处理。在下列的代码中,从一个拖放源拖入一个listView控件,我们是通过判断拖放数据类型来确定是否接受拖放,如果是字符串,则可以,否则,则不行。具体代码如下:
private void listView1_DragEnter ( object sender , DragEventArgs e )
{
//判断是否目前拖动的数据是字符串,如果是,则拖动符串对目的组件进行拷贝
if ( e.Data.GetDataPresent ( DataFormats.Text ) )
e.Effect = DragDropEffects.Move ;
else
e.Effect = DragDropEffects.None ;
}
当目标控件不接受一个拖放操作的时候,光标会变成一个禁止标示。
(3) 获得拖放的数据,在目标组件中加入相应的内容:
此步的处理过程是十分明确的,要分成二步来进行,首先要得到拖放的字符串,其次是在目标组件中加入以此字符串为标题的项目。当然还要在相应的位置了。下面就是实现这二步操作的具体代码:
private void listView1_DragDrop ( object sender , DragEventArgs e )
{
string dummy = "temp" ;
//获得进行"Drag"操作中拖动的字符串
string s = (string) e.Data.GetData (dummy.GetType()) ;
s = s.Substring (s.IndexOf":")+1).Trim() ;
//在目标组件中加入以此字符串为标题的项目
listView1.Items.Add ( new ListViewItem ( s , 0 ) ) ;
e.Effect = DragDropEffects.Copy;
}
此致通过对这三个事件的编程,已经完成了由TreeView组件到ListView组件的拖放操作,