【问题标题】:How to drag images from a listview (together with an imageview) to pictureboxes?如何将图像从列表视图(连同图像视图)拖到图片框?
【发布时间】:2015-12-31 11:12:00
【问题描述】:

我对 C# 还很陌生,并且在我想做的一个小项目上遇到了很多困难。

我正忙于制作拼贴画之类的东西我的拼贴画。

我想展示一张图片,但我不能发布低于 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 窗体中使用 C# 完成。

【问题讨论】:

  • 如果您想将图像放入特定的插槽以形成拼贴,那么我可以帮助您。我的意思是,您可以将正确的图片框拆分为 9 个(或其他)图片框。然后,您可以编写代码以使图像落入插槽,从而形成图像。另一方面,如果你想要重叠的图像可以放在图片框内的任何地方,那就更难了。
  • @FarhanAnam 好的,我认为这将是一个很好的开始。
  • Farhan 解决了第一个也是最重要的问题:您希望图像重叠(如拼贴)还是不重叠(如图片库)?您需要对此做出决定,然后我们才能就如何以最佳方式进行提供建议。第二个问题是目标是否应在放置后可编辑/可移动?
  • 好吧,图像必须彼此相对,彼此之间没有任何间隙。其目的主要是为了将航拍照片拼接在一起,使其看起来像一张地图。这意味着它们也必须以正确的顺序组织起来。通过使图像重叠成为可能,之后将提高图像的精度,因为用户可以手动微调所有内容。

标签: c# winforms listview drag-and-drop picturebox


【解决方案1】:

这是一个您可能想玩的完整示例:

它使用带有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);
        }
    }
}

或者更新)为ListViews 在他们的ItemDrag 活动中更好、更简单(感谢汉斯!):

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

更新:现在两种方式都使用拖动的 Item,而不仅仅是它的 imageIndex,以便更简单地从 LV 中删除 Item..

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。因此,您可能只想使用索引并使用它从磁盘加载更大的图像..

【讨论】:

  • 第一个;非常感谢您花时间和精力帮助我。我做了你所做的一切,现在我的listview 中有这 10 个项目。但是当我点击某个东西然后将它拖到panel 时,我得到一个异常“An exception of type 'System.ArgumentOutOfRangeException' occurred in System.Windows.Forms.dll but was not handled in user code Additional information: InvalidArgument=Value of '1' is not valid for 'index'.
  • 我是在什么地方理解错了还是我做错了什么?我只是先在一个新的win-forms项目上试了一下,把所有的代码sn-ps都插在了一个下面
  • 嗯,这听起来好像你的图像列表是空的?请注意,我正在更新答案,利用 Hans 的(现在删除的)答案来帮助您从列表视图中删除拖动的项目,仅使用图像索引有点困难..
  • Pfff 对不起,我的错,我很快开始了一个新项目来尝试它并忘记添加图像 - 到目前为止它工作得很好!
  • 查看更新后的答案;使用 ListViewItem 作为被拖动对象更简单灵活..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-08
  • 1970-01-01
  • 1970-01-01
  • 2012-10-23
  • 1970-01-01
相关资源
最近更新 更多