trevor1940
asked on
C#: How to Drag n Drop
Hi
I'm trying to work out how to do drag and drop on a form
I've worked out how to get the path of folder dragged from explorer into a text box
I now need to drag between ListViews and from Explorer
My form has 4 elements
1 Text box => FolderTxtBox
2 ListViews => MoviesLV & ImagesLV (AllowDrop = True)
1 Button => Rename (Code not yet implemented)
Basic Flow
On Dragging a folder from Explorer onto FolderTxtBox a list of movies and matching jpg's is shown in MoviesLV and any jpg's not used are shown in ImagesLV
I want to be able to drag a jpg from ImagesLV in to the Image Name column of MoviesLV
or
If this doesn't exist from Explorer
The Code bellow is based on this example
I'm trying to work out how to do drag and drop on a form
I've worked out how to get the path of folder dragged from explorer into a text box
I now need to drag between ListViews and from Explorer
My form has 4 elements
1 Text box => FolderTxtBox
2 ListViews => MoviesLV & ImagesLV (AllowDrop = True)
1 Button => Rename (Code not yet implemented)
Basic Flow
On Dragging a folder from Explorer onto FolderTxtBox a list of movies and matching jpg's is shown in MoviesLV and any jpg's not used are shown in ImagesLV
I want to be able to drag a jpg from ImagesLV in to the Image Name column of MoviesLV
or
If this doesn't exist from Explorer
The Code bellow is based on this example
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows;
using System.IO;
using System.Collections;
namespace DragDropLV
{
public partial class Form1 : Form
{
new HashSet<String> JpgFileEntries = new HashSet<String>();
bool Mlv_mdown = false;
bool Jlv_mdown = false;
public Form1()
{
// link https://www.c-sharpcorner.com/article/imlememnting-drag-and-drop-in-listview-controls/
InitializeComponent();
// Set up the List View
MoviesLV.View = View.Details;
MoviesLV.Columns.Add("Video Name", 100, HorizontalAlignment.Left);
MoviesLV.Columns.Add("Image Name", 100, HorizontalAlignment.Left);
ImagesLV.View = View.Details;
ImagesLV.Columns.Add("Image Name", 100, HorizontalAlignment.Left);
ImagesLV.Columns.Add("Last Modified", 100, HorizontalAlignment.Left);
}
private void Form1_Load(object sender, EventArgs e)
{
// Set up Drag N Drop
// To get the text box working code needed to be here
FolderTxtBox.AllowDrop = true;
FolderTxtBox.DragEnter += new DragEventHandler(FolderTxtBox_DragEnter);
FolderTxtBox.DragDrop += new DragEventHandler(FolderTxtBox_DragDrop);
MoviesLV.DragEnter += new DragEventHandler(MoviesLV_DragEnter);
MoviesLV.DragDrop += new DragEventHandler(MoviesLV_DragDrop);
ImagesLV.DragEnter += new DragEventHandler(ImagesLV_DragEnter);
ImagesLV.DragDrop += new DragEventHandler(ImagesLV_DragDrop);
}
private void Load_ListViews(string DirPath)
{
if (Directory.Exists(DirPath) )
{
var mFiles = Directory.EnumerateFiles(DirPath, "*", SearchOption.TopDirectoryOnly).Where(s => s.EndsWith(".mp4") || s.EndsWith(".mkv") || s.EndsWith(".avi")); ;
foreach (string mFile in mFiles)
{
FileInfo FI = new FileInfo(mFile);
string fName = FI.Name;
string jFile = Path.ChangeExtension(mFile, "jpg");
ListViewItem item = new ListViewItem();
item.Text = fName;
if (File.Exists(jFile))
{
FileInfo JI = new FileInfo(jFile);
string jName = JI.Name;
item.SubItems.Add(jName);
JpgFileEntries.Add(JI.FullName);
}
// To Do Best guess for other jpg's using RegEx
MoviesLV.Items.Add(item);
}
// What's left needs manual choice
var jpgFiles = Directory.EnumerateFiles(DirPath, "*", SearchOption.TopDirectoryOnly).Where(s => s.EndsWith(".jpg") || s.EndsWith(".jpeg"));
foreach (string jpgFile in jpgFiles)
{
FileInfo JI = new FileInfo(jpgFile);
string jName = JI.Name;
if (JpgFileEntries.Add(jpgFile))
{
ListViewItem item = new ListViewItem();
item.Text = jName;
item.SubItems.Add(JI.LastAccessTime.ToShortDateString());
ImagesLV.Items.Add(item);
}
}
}
}
private void FolderTxtBox_DragDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
if (Directory.Exists(files[0]))
{
this.FolderTxtBox.Text = files[0];
Load_ListViews(FolderTxtBox.Text);
}
}
}
private void FolderTxtBox_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effect = DragDropEffects.Copy;
}
else
{
e.Effect = DragDropEffects.None;
}
}
private void MoviesLV_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
string textBox1 = e.Data.GetData(DataFormats.Text).ToString();
string[] items = textBox1.Split(',');
MoviesLV.Items.Add(new ListViewItem(items, 0));
Mlv_mdown = false;
Jlv_mdown = false;
}
private void MoviesLV_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.Text))
e.Effect = DragDropEffects.Copy;
else
e.Effect = DragDropEffects.None;
}
private void MoviesLV_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (!Mlv_mdown) return;
if (e.Button == MouseButtons.Right) return;
string str = GetItemText(MoviesLV);
if (str == "") return;
MoviesLV.DoDragDrop(str, DragDropEffects.Copy | DragDropEffects.Move);
}
private void MoviesLV_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
Mlv_mdown = true;
}
private void ImagesLV_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.Text))
e.Effect = DragDropEffects.Copy;
else
e.Effect = DragDropEffects.None;
}
private void ImagesLV_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
string textBox1 = e.Data.GetData(DataFormats.Text).ToString();
string[] items = textBox1.Split(',');
ImagesLV.Items.Add(new ListViewItem(items, 0));
Jlv_mdown = false;
Mlv_mdown = false;
}
private void ImagesLV_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (!Jlv_mdown) return;
if (e.Button == MouseButtons.Right) return;
string str = GetItemText(ImagesLV);
if (str == "") return;
ImagesLV.DoDragDrop(str, DragDropEffects.Copy | DragDropEffects.Move);
}
private void ImagesLV_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
Jlv_mdown = true;
}
public string GetItemText(ListView LVIEW)
{
int nTotalSelected = LVIEW.SelectedIndices.Count;
if (nTotalSelected <= 0) return "";
IEnumerator selCol = LVIEW.SelectedItems.GetEnumerator();
selCol.MoveNext();
ListViewItem lvi = (ListViewItem)selCol.Current;
string mDir = "";
for (int i = 0; i < lvi.SubItems.Count; i++)
mDir += lvi.SubItems[i].Text + ",";
mDir = mDir.Substring(0, mDir.Length - 1);
return mDir;
}
}
}
ASKER
Hi
This is a good start thanx
My ultimate goal is to create a UI for renaming jpg's to movies so the file name is the same just different extensions
When I drag a single image name from lvImages on to lvMovies a new row is created (PIC)
I need to be able to drag to a specific row (replacing what's there)
eg
"SampleVideo_3.mkv" -> "images.jpg" (same Row not like the pic.)
Dragging from Explorer isn't implemented
This is a good start thanx
My ultimate goal is to create a UI for renaming jpg's to movies so the file name is the same just different extensions
When I drag a single image name from lvImages on to lvMovies a new row is created (PIC)
I need to be able to drag to a specific row (replacing what's there)
eg
"SampleVideo_3.mkv" -> "images.jpg" (same Row not like the pic.)
Dragging from Explorer isn't implemented
ASKER
Hi
Just been googling should I be using a DataGridView instead of a Listview?
These seem to be editable?
Just been googling should I be using a DataGridView instead of a Listview?
These seem to be editable?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hi
I've been looking through your code worked out how to drag a File.jpg from explorer on to lvMovies could you have a look at my changes (marked with ###) to OnDragEnter and OnDragDrop to see if this is the best way?
Form1.cs
I've been looking through your code worked out how to drag a File.jpg from explorer on to lvMovies could you have a look at my changes (marked with ###) to OnDragEnter and OnDragDrop to see if this is the best way?
Form1.cs
using System;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
namespace EE_Q29149321
{
public partial class Form1 : Form
{
bool isImagesMouseDown;
bool isMoviesMouseDown;
// ### Hold a used list of jpg's
new HashSet<String> JpgFileEntries = new HashSet<String>();
string DataFormat { get; set; }
public Form1()
{
InitializeComponent();
// ### Folder with *.mp4's and *.jpg's to load into the ListView
Load_ListViews(@"E:\Temp");
}
private void Load_ListViews(string DirPath)
{
if (Directory.Exists(DirPath))
{
var mFiles = Directory.EnumerateFiles(DirPath, "*", SearchOption.TopDirectoryOnly).Where(s => s.EndsWith(".mp4") || s.EndsWith(".mkv") || s.EndsWith(".avi")); ;
foreach (string mFile in mFiles)
{
FileInfo FI = new FileInfo(mFile);
string fName = FI.Name;
string jFile = Path.ChangeExtension(mFile, "jpg");
ListViewItem item = new ListViewItem();
item.Text = fName;
if (File.Exists(jFile))
{
FileInfo JI = new FileInfo(jFile);
string jName = JI.Name;
item.SubItems.Add(jName);
JpgFileEntries.Add(JI.FullName);
}
else
{
item.SubItems.Add("");
}
// To Do Best guess for other jpg's using RegEx
lvMovies.Items.Add(item);
}
// What's left needs manual choice
var jpgFiles = Directory.EnumerateFiles(DirPath, "*", SearchOption.TopDirectoryOnly).Where(s => s.EndsWith(".jpg") || s.EndsWith(".jpeg"));
foreach (string jpgFile in jpgFiles)
{
FileInfo JI = new FileInfo(jpgFile);
string jName = JI.Name;
if (JpgFileEntries.Add(jpgFile))
{
ListViewItem item = new ListViewItem();
item.Text = jName;
item.SubItems.Add(JI.LastAccessTime.ToShortDateString());
lvImages.Items.Add(item);
}
}
}
}
private void OnLoad(object sender, EventArgs e)
{
AllowDrop = lvMovies.AllowDrop = lvImages.AllowDrop = true;
lvMovies.View = lvImages.View = View.Details;
lvMovies.FullRowSelect = lvImages.FullRowSelect = true;
lvMovies.Columns
.AddRange(new[]
{
new ColumnHeader() { Text = "Video Name", Width = 100, TextAlign = HorizontalAlignment.Left },
new ColumnHeader() { Text = "Image Name", Width = 100, TextAlign = HorizontalAlignment.Left }
});
//lvMovies.Items.AddRange(Enumerable.Range(0, 5).Select(i => new ListViewItem(new[] { $"Movie{i}", $"Image{i}" })).ToArray());
lvImages.Columns
.AddRange(new[]
{
new ColumnHeader() { Text = "Image Name", Width = 100, TextAlign = HorizontalAlignment.Left },
new ColumnHeader() { Text = "Last Modified", Width = 100, TextAlign = HorizontalAlignment.Left }
});
//lvImages.Items.AddRange(Enumerable.Range(5, 5).Select(i => new ListViewItem(new[] { $"Image{i}", $"{DateTime.Now.AddDays(i)}" })).ToArray());
}
private void OnDragEnter(object sender, DragEventArgs e)
{
// Work out the format of what's being dragged and set DataFormat
if (e.Data.GetDataPresent(DataFormats.Text))
{
e.Effect = DragDropEffects.Copy;
DataFormat = "text";
}
// ####
else if(e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effect = DragDropEffects.Copy;
DataFormat = "FileDrop";
}
else
{
e.Effect = DragDropEffects.None;
}
}
private void OnDragDrop(object sender, DragEventArgs e)
{
if (sender is ListView)
{
var lv = sender as ListView;
var text = "";
// ### didn't know if other options exist hence switch
switch (DataFormat)
{
case "text":
// from a listview => FileName.jpg,Date
text = e.Data.GetData(DataFormats.Text).ToString();
break;
case "FileDrop":
// from exploror
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
foreach (string file in files)
{
// emulate text from ListView
if (Path.GetExtension(file) == ".jpg")
{
FileInfo JI = new FileInfo(file);
string jName = JI.Name;
string ModDate = JI.LastAccessTime.ToShortDateString();
text = jName + "," + ModDate;
}
}
break;
}
var point = lv.PointToClient(new Point(e.X, e.Y));
var hovered = lv.GetItemAt(point.X, point.Y);
if (!string.IsNullOrWhiteSpace(text))
{
var items = text.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries).Select(i => i.Split(new[] { "," }, StringSplitOptions.None)).ToList();
if (lv.Equals(lvImages) && isMoviesMouseDown)
{
if (hovered == null)
{
lv.Items.AddRange(items.Select(i => new ListViewItem(new[] { i[1], DateTime.MinValue.ToString() })).ToArray());
}
else
{
hovered.Text = items[0][1];
}
foreach (var item in lvMovies.SelectedItems.Cast<ListViewItem>().Reverse())
{
lvMovies.Items.Remove(item);
}
}
else if (lv.Equals(lvMovies) && isImagesMouseDown)
{
if (hovered == null)
{
lv.Items.AddRange(items.Select(i => new ListViewItem(new[] { "Untitled", i[0] })).ToArray());
}
else
{
hovered.SubItems[1].Text = items[0][0];
}
foreach (var item in lvImages.SelectedItems.Cast<ListViewItem>().Reverse())
{
lvImages.Items.Remove(item);
}
}
// ### File dropped from Explorer
// ### Not sure if this is good
else if (lv.Equals(lvMovies) && DataFormat == "FileDrop")
{
hovered.SubItems[1].Text = items[0][0];
}
}
}
isMoviesMouseDown = false;
isImagesMouseDown = false;
}
private void OnMouseDown(object sender, MouseEventArgs e)
{
if (sender is ListView)
{
var lv = sender as ListView;
if (lv.Equals(lvImages))
{
isImagesMouseDown = true;
}
else if (lv.Equals(lvMovies))
{
isMoviesMouseDown = true;
}
}
}
private void OnMouseMove(object sender, MouseEventArgs e)
{
if (sender is ListView)
{
var lv = sender as ListView;
if ((lv.Equals(lvImages) && !isImagesMouseDown) || (lv.Equals(lvMovies) && !isMoviesMouseDown) || e.Button.Equals(MouseButtons.Right))
{
return;
}
var text = lv.GetItemText();
if (string.IsNullOrWhiteSpace(text))
{
return;
}
lv.DoDragDrop(text, DragDropEffects.Copy | DragDropEffects.Move);
}
}
}
// This gets fired every time the mouse moves, No idea why?
static class Extensions
{
public static string GetItemText(this ListView lv)
{
if (lv.SelectedIndices.Count <= 0)
{
return "";
}
return $"{string.Join("|", lv.SelectedItems.Cast<ListViewItem>().Select(i => $"{string.Join(",", i.SubItems.Cast<ListViewItem.ListViewSubItem>().Select(s => s.Text))}"))}";
}
}
}
ASKER
Thanx Very much
Form1.cs -
Open in new window
Form1.Designer.cs -Open in new window
Which produces the following results --saige-