65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.72/5 (79投票s)

2002年3月24日

CPOL

6分钟阅读

viewsIcon

448065

downloadIcon

11529

.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 枚举
成员名称 描述
全部 数据被复制,从拖动源中移除,并在放置目标中滚动。
复制 数据被复制到放置目标。
链接 来自拖动源的数据链接到放置目标。
移动 来自拖动源的数据移动到放置目标。
放置目标不接受数据。
Scroll 放置目标中的滚动即将开始或正在进行中。
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)); 
    } 
}

好了,既然我们已经设置了拖放源,我们就需要处理拖放目标,对于我们来说,那就是右边的列表框。拖放目标有四个相关的事件。事件是 DragEnterDragOverDragDropDragLeave。当鼠标指针将某个东西拖入控件的客户区时,就会发生 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 对象作为第二个参数传递给我们。它有一个名为 DataIDataObject 成员。我们调用其上的 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 电子邮件地址。对我来说,那不是一个快速的服务器,我也不喜欢从那里收到太多的邮件。谢谢。

© . All rights reserved.