如何将图像从列表视图(连同图像视图)拖到图片框?

How to drag images from a listview (together with an imageview) to pictureboxes?

我是 C# 的新手,在我想做的一个小项目上遇到了很多困难。

我正忙于制作拼贴画之类的东西,我在左侧有一个图片列表,我想将多张图像拖放到右侧,以便能够移动它们创建我的拼贴画。

我想展示一张图片,但不允许 post 声誉点数低于 10 的图片。但是在这里寻找 image:

我无法让它工作。我在网上寻求帮助,但我真的找不到我要找的东西。我发现的东西太不清楚了,我很难理解。

这就是我目前所掌握的从左向右拖放的代码,但它不起作用;

private void pictureBox1_DragEnter(object sender, DragEventArgs e)
    {
        int len = e.Data.GetFormats().Length - 1;
        int i;
        for (i = 0; i <= len; i++)
        {
            if (e.Data.GetFormats()[i].Equals("System.Windows.Forms.ListView+SelectedListViewItemCollection"))
            {
                //The data from the drag source is moved to the target.
                e.Effect = DragDropEffects.Move;
            }
        }
    }

    private void pictureBox1_DragDrop(object sender, DragEventArgs e)
    {
        //Return if the items are not selected in the ListView control.
        if (listView1.SelectedItems.Count == 0)
        {
            return;
        }
        ListViewItem dragitem = listView1.SelectedItems[0];
        pictureBox2.Image = imageList1.Images[dragitem.ImageIndex];
        listView1.Items.Remove(dragitem);
    }

    private void listView1_MouseDown(object sender, MouseEventArgs e)
    {
        listView1.DoDragDrop(listView1.SelectedItems, DragDropEffects.Move);
    }

我可以在左侧添加图像后,如何使用鼠标坐标拖动和移动它们?

如有任何帮助,我们将不胜感激。 一切都是在 Windows Forms 中使用 C# 完成的。

这里有一个完整的例子,你可能想玩一下:

它使用带有 ListViewImageListPanel 的形式来保存 PictureBoxes

您可以使用 FlowLayoutPanel,但这不会让您稍后移动 Pictureboxes

您还可以使用 Panels 及其 BackgroundImage 的网格。

首先我们设置表格:

private void Form1_Load(object sender, EventArgs e)
{
    KeyPreview = true;
    FillLV(10);
    AddPBs(36);
    listView1.MouseMove += listView1_MouseMove;
}

void FillLV(int count)
{
    for (int i = 0; i < count; i++) listView1.Items.Add("Item" + i, i);
}

void AddPBs(int count)
{
    int iWidth = imageList1.ImageSize.Width;
    int iHeight = imageList1.ImageSize.Height;
    int cols = panel1.ClientSize.Width / iWidth;

    for (int i = 0; i < count; i++)
    {
        PictureBox PB = new PictureBox();
        PB.BackColor = Color.LightGray;
        PB.Margin = new System.Windows.Forms.Padding(0);
        PB.ClientSize = new System.Drawing.Size(iWidth , iHeight );
        PB.Location = new Point(iWidth * (i % cols), iHeight * (i / cols));
        PB.Parent = panel1;
        PB.DragEnter += PB_DragEnter;
        PB.DragDrop += PB_DragDrop;
        PB.AllowDrop = true;
        PB.MouseClick += (ss, ee) => { currentPB = PB; PB.Focus(); };
    }
}

请注意我们如何将事件添加到动态创建的 PictureBoxes 以及我们如何设置它们的隐藏 AllowDrop 属性.

另请注意小 lambda,使 MouseClick 准备好使用键盘移动它们。

为此,我们还需要对当前框的引用:

PictureBox currentPB = null;

现在我们开始拖动。这应该 MouseDown 中完成,否则它会干扰正常选择,并且也会在做出新选择之前发生..

要么你在MouseMove:

void listView1_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == System.Windows.Forms.MouseButtons.Left)
    {
        if (listView1.SelectedItems.Count > 0)
        {
            listView1.DoDragDrop(listView1.SelectedItems[0], DragDropEffects.Move);
        }
    }
}

Or (Update) ListViews 更好更简单(感谢 Hans!)在他们的 ItemDrag 事件:

private void listView1_ItemDrag(object sender, ItemDragEventArgs e)
{
    listView1.DoDragDrop(e.Item, DragDropEffects.Move);
}

更新:两种方式现在都使用拖动的项目,而不仅仅是其图像索引,以便更容易从 LV 中删除项目..

void PB_DragEnter(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(typeof(ListViewItem))) 
        e.Effect = DragDropEffects.Move;
    else
        e.Effect = DragDropEffects.None;
}

void PB_DragDrop(object sender, DragEventArgs e)
{
    PictureBox pb = sender as PictureBox;
    var item = (ListViewItem)e.Data.GetData(typeof(ListViewItem));
    int index = item.ImageIndex;
    pb.Image = imageList1.Images[index];  // make sure you have images for indices!!

}

最后我们使用键盘移动当前框。我还添加了代码以在 z 顺序中上下移动它。

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (currentPB == null) return;
    if (e.KeyData == Keys.Left) currentPB.Left -= 1;
    else if (e.KeyData == Keys.Right) currentPB.Left += 1;
    else if (e.KeyData == Keys.Up) currentPB.Top -= 1;
    else if (e.KeyData == Keys.Down) currentPB.Top += 1;
    else
    { 
        int z = panel1.Controls.GetChildIndex(currentPB);
        if (e.KeyData == Keys.Home) panel1.Controls.SetChildIndex(currentPB, 0);
        else if (e.KeyData == Keys.End) 
             panel1.Controls.SetChildIndex(currentPB, panel1.Controls.Count);
        else if (e.KeyData == Keys.PageUp) 
             panel1.Controls.SetChildIndex(currentPB, z + 1);
        else if (e.KeyData == Keys.PageDown) 
             { if (z > 0) panel1.Controls.SetChildIndex(currentPB, z - 1); }
    }
    panel1.Invalidate();

}

为此,表单必须具有:KeyPreview = true;

请注意 ImageList 中的尺寸限制为 256x256。所以你可能只想使用索引并使用它从磁盘加载更大的图像..