列表框之间的拖放——初学者教程






4.72/5 (79投票s)
.NET 中的拖放入门
前导码
是的,当您梦想着拖放时,您并不孤单。我也曾梦想过。当您感受到鼠标的力量时,那是一种无限的欣喜。只需单击一个项目,将其拖到另一个窗口或控件上,然后简单地将其放在那里,就会给您一种至高无上的感觉。好了,我想我最好停止这种幼稚的胡言乱语,开始谈论严肃的事情了。就在今天早上,我还在想,在 .NET 中拖放应该很容易,因为每当我尝试用 .NET 做什么时,我基本上都会遇到这种情况。与处理普通的 SDK/MFC 东西或非 .NET 东西相比,一切总是容易得多。
我创建了一个简单的 C# Windows 窗体应用程序。然后,我使用窗体设计器添加了两个列表框。现在我的意图是用一些文本填充左边的列表框。在我完成这个小示例程序时,我应该能够将左边列表框中的一个项目拖放到右边列表框中。这应该只需要我大约一个小时左右的时间,但我确实在一个点上卡住了,幸运的是,James T Johnson 提供了一些建议,解决了我的所有问题。他真是一个了不起的角色,那个 JTJ,您需要非常亲近才能感受到这一点。
屏幕截图
好吧,在我们继续之前,您可以看看用 *咳咳* Windows XP Professional 制作的屏幕截图。我知道你们大多数人现在都在想,如果他认为使用 XP 是一件大事,这个人似乎疯了。但唉,他们不知道像我这样的第三世界国家所面临的艰辛。事实上,我还未使用 DOS 5.0 已经是一种好运了。是的,情况就是这么糟糕。
我们继续吧
我们从中拖动项目的控件称为拖放源。在我们的例子中,这将是左边的列表框。同样,我们最终将拖动项目放置在上面的控件称为拖放目标,对于我们来说,这将是右边的列表框。对于以前没有拖放过的朋友们 [特别是来自 Linux 背景的人们],完成这个操作非常简单。单击一个项目,现在不要将手指从鼠标按钮上移开,将鼠标光标拖到另一个点,然后释放鼠标按钮,从而将项目放置在该精确点上。确保将其放置在拖放目标控件或窗口上,否则整个练习将毫无意义。
我们需要做的第一件事是确保右边的列表框是一个放置目标。控件有一个名为 AllowDrop
的属性,我们需要将其设置为 true。您可以通过窗体设计器或通过代码手动完成此操作。
this.listBox2.AllowDrop = true;
现在我们需要为左边列表框的 MouseDown
事件添加一个处理程序。当您单击列表框控件内的任何位置时,就会发生 MouseDown
事件。
this.listBox1.MouseDown += new MouseEventHandler(
this.listBox1_MouseDown);
好吧,MouseDown
处理程序本身很简单。首先,我们弄清楚在单击时,鼠标下方是哪个项目。为此,我们使用 IndexFromPoint
函数,结果证明它正是我想要的。詹姆斯在这里给了我巨大的帮助。当我在黑暗的深渊中像醉猫一样摸索时,他向我指出了这个很棒的小函数。好吧,今天我真是停不下对 JTJ 的赞美。各位,请原谅我。
一旦我们获得了要拖动的文本,我们就调用 DoDragDrop
函数。此函数接受两个参数。
public DragDropEffects DoDragDrop(object data,
DragDropEffects allowedEffects);
第一个参数是从拖放源拖出的对象。在我们的例子中,这将是鼠标下方列表框中项目的文本。第二个参数是 DragDropEffects
枚举。我在下表向您展示了各种可能的值。当然,您也可以在 MSDN 中查找。我正在使用 DragDropEffects.All
,因为这就是我们所做的。我们将数据复制到目标,并从源中删除它。我们需要检查 DoDragDrop
返回的值,如果它等于 DragDropEffects.All
,这意味着该项目已成功放置在有效目标上,因此我们从列表框中删除该项目。否则,我们不应该删除它,因为它意味着放置是在一个无意义的区域完成的。
DragDropEffects 枚举 | ||||||||||||||
|
private void listBox1_MouseDown(
object sender, System.Windows.Forms.MouseEventArgs e)
{
if(listBox1.Items.Count==0)
return;
int index = listBox1.IndexFromPoint(e.X,e.Y);
string s = listBox1.Items[index].ToString();
DragDropEffects dde1=DoDragDrop(s,
DragDropEffects.All);
if(dde1 == DragDropEffects.All )
{
listBox1.Items.RemoveAt(listBox1.IndexFromPoint(e.X,e.Y));
}
}
好了,既然我们已经设置了拖放源,我们就需要处理拖放目标,对于我们来说,那就是右边的列表框。拖放目标有四个相关的事件。事件是 DragEnter
、DragOver
、DragDrop
和 DragLeave
。当鼠标指针将某个东西拖入控件的客户区时,就会发生 DragEnter
。如果鼠标在不放置项目的情况下将其拖出控件的客户区,则会发生 DragLeave
。我们不会关心这两个事件。
DragOver
事件发生在 DragEnter
事件之后,我们需要通过将传递给处理程序的 DragEventsArg
对象中的 Effect
属性设置为 DragDropEffects
枚举之一来指示我们已准备好接受放置的项目。如果我们将其设置为 DragDropEvents.None
,那么我们就 фактически 拒绝了放置。
private void listBox2_DragOver(
object sender, System.Windows.Forms.DragEventArgs e)
{
e.Effect=DragDropEffects.All;
}
如果鼠标在控件的客户区域上方释放,则会发生 DragDrop
事件。如果我们没有表明接受放置的意愿,那么将不会发生 DragDrop
事件,而是会发生 DragLeave
事件。我们将一个 DragEventArgs
对象作为第二个参数传递给我们。它有一个名为 Data
的 IDataObject
成员。我们调用其上的 GetDataPresent
成员函数来验证数据中的数据格式是我们期望的。在我们的例子中,我们期望的是一个字符串。所以我们用 DataFormats.StringFormat.
进行检查。然后,一旦我们确定数据格式正确,我们就调用 GetData
来检索我们的字符串并将其添加到我们的列表框中。
private void listBox2_DragDrop(
object sender, System.Windows.Forms.DragEventArgs e)
{
if(e.Data.GetDataPresent(DataFormats.StringFormat))
{
string str= (string)e.Data.GetData(
DataFormats.StringFormat);
listBox2.Items.Add(str);
}
}
我想这就是全部了。这只是对拖放的一个最小介绍。但是您可以进一步探索它。请随意在文章论坛上发表您的评论,但请不要直接给我发邮件,尤其是不要发送到我的 busterboy.org 电子邮件地址。对我来说,那不是一个快速的服务器,我也不喜欢从那里收到太多的邮件。谢谢。