将 MP3 拖到 C# 中的 ListView
Drag MP3's to ListView in C#
我目前正在开发自己的 MP3 播放器,并希望添加拖放功能,以便能够一次拖放一个文件或一次拖放整个目录。我将 ListView 的视图设置为详细信息,并使用以下代码:
void Playlist_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Copy;
}
void Playlist_DragDrop(object sender, DragEventArgs e)
{
Playlist.Items.Clear();
string[] songs = (string[])e.Data.GetData(DataFormats.FileDrop, false);
Parallel.ForEach(songs, s =>
{
if (File.Exists(s))
{
if (string.Compare(Path.GetExtension(s), ".mp3", true) == 0)
{
MessageBox.Show(s);
AddFileToListview(s);
}
}
else if (Directory.Exists(s))
{
DirectoryInfo di = new DirectoryInfo(s);
FileInfo[] files = di.GetFiles("*.mp3");
foreach (FileInfo file in files)
{
AddFileToListview(file.FullName);
MessageBox.Show(file.FullName);
}
}
});
}
private void AddFileToListview(string fullFilePath)
{
if (!File.Exists(fullFilePath))
return;
string song = Path.GetFileName(fullFilePath);
string directory = Path.GetDirectoryName(fullFilePath);
if (directory.EndsWith(Convert.ToString(Path.DirectorySeparatorChar)))
directory = directory.Substring(0, directory.Length - 1); //hack off the trailing \
ListViewItem itm = Playlist.Items.Add(song);
itm.SubItems.Add(directory); //second column = path
}
我在其中安装了 MessageBox 以确保我的代码被命中并且 tit 始终向我显示正确的数据但 ListView 中没有任何显示。知道我做错了什么吗?
@ClearLogic:你是对的,我忘了在 ListView 中定义列,谢谢。现在我有另一个问题,我可以毫无问题地将多个目录拖到 ListView 中,但是当我尝试添加多个单个 MP3 时,我在行上遇到了跨线程异常
ListViewItem itm = Playlist.Items.Add(song);
感谢@ClearLogic 为解决这个问题提供的所有帮助,我想我会分享我的代码以防其他人也遇到一些问题。
private void Playlist_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Copy;
}
private void Playlist_DragDrop(object sender, DragEventArgs e)
{
//get the file names
string[] songs = (string[])e.Data.GetData(DataFormats.FileDrop, false);
//we're using a Parallel.ForEach loop because if a directory is selected it can contain n number of items, this is to help prevent a bottleneck.
Parallel.ForEach(songs, song =>
{
//make sure the file exists
if (File.Exists(song))
{
//if it's an mp3 file then call AddFileToListview
if (string.Compare(Path.GetExtension(song), ".mp3", true) == 0)
{
AddFileToListview(song);
}
}
//A HA! It's a directory not a single file
else if (Directory.Exists(song))
{
//get the directory information
DirectoryInfo di = new DirectoryInfo(song);
//get all the mp3 files (will add WMA in the future)
FileInfo[] files = di.GetFiles("*.mp3");
//here we use a parallel loop to loop through every mp3 in the
//directory provided
Parallel.ForEach(files, file =>
{
AddFileToListview(file.FullName);
});
}
});
}
private void AddFileToListview(string fullFilePath)
{
double nanoseconds;
string totalTime = string.Empty;
//First things first, does the file even exist, if not then exit
if (!File.Exists(fullFilePath))
return;
//get the song name
string song = Path.GetFileName(fullFilePath);
//get the directory
string directory = Path.GetDirectoryName(fullFilePath);
//hack off the trailing \
if (directory.EndsWith(Convert.ToString(Path.DirectorySeparatorChar)))
directory = directory.Substring(0, directory.Length - 1);
//now we use the WindowsAPICodePack.Shell to start calculating the songs time
ShellFile shell = ShellFile.FromFilePath(fullFilePath);
//get the length is nanoseconds
double.TryParse(shell.Properties.System.Media.Duration.Value.ToString(), out nanoseconds);
//first make sure we have a value greater than zero
if (nanoseconds > 0)
{
// double milliseconds = nanoseconds * 0.000001;
TimeSpan time = TimeSpan.FromSeconds(Utilities.ConvertToMilliseconds(nanoseconds) / 1000);
totalTime = time.ToString(@"m\:ss");
}
//build oour song data
ListViewItem item = new ListViewItem();
item.Text = song;
item.SubItems.Add(totalTime);
//now my first run at this gave me a cross-thread exception when trying to add multiple single mp3's
//but I could add all the whole directories I wanted, o that is why we are now using BeginINvoke to access the ListView
if (Playlist.InvokeRequired)
Playlist.BeginInvoke(new MethodInvoker(() => Playlist.Items.Add(item)));
else
Playlist.Items.Add(item);
}
此代码使用 WindowsAPICodePack 来计算每首歌曲的时间。
我目前正在开发自己的 MP3 播放器,并希望添加拖放功能,以便能够一次拖放一个文件或一次拖放整个目录。我将 ListView 的视图设置为详细信息,并使用以下代码:
void Playlist_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Copy;
}
void Playlist_DragDrop(object sender, DragEventArgs e)
{
Playlist.Items.Clear();
string[] songs = (string[])e.Data.GetData(DataFormats.FileDrop, false);
Parallel.ForEach(songs, s =>
{
if (File.Exists(s))
{
if (string.Compare(Path.GetExtension(s), ".mp3", true) == 0)
{
MessageBox.Show(s);
AddFileToListview(s);
}
}
else if (Directory.Exists(s))
{
DirectoryInfo di = new DirectoryInfo(s);
FileInfo[] files = di.GetFiles("*.mp3");
foreach (FileInfo file in files)
{
AddFileToListview(file.FullName);
MessageBox.Show(file.FullName);
}
}
});
}
private void AddFileToListview(string fullFilePath)
{
if (!File.Exists(fullFilePath))
return;
string song = Path.GetFileName(fullFilePath);
string directory = Path.GetDirectoryName(fullFilePath);
if (directory.EndsWith(Convert.ToString(Path.DirectorySeparatorChar)))
directory = directory.Substring(0, directory.Length - 1); //hack off the trailing \
ListViewItem itm = Playlist.Items.Add(song);
itm.SubItems.Add(directory); //second column = path
}
我在其中安装了 MessageBox 以确保我的代码被命中并且 tit 始终向我显示正确的数据但 ListView 中没有任何显示。知道我做错了什么吗?
@ClearLogic:你是对的,我忘了在 ListView 中定义列,谢谢。现在我有另一个问题,我可以毫无问题地将多个目录拖到 ListView 中,但是当我尝试添加多个单个 MP3 时,我在行上遇到了跨线程异常
ListViewItem itm = Playlist.Items.Add(song);
感谢@ClearLogic 为解决这个问题提供的所有帮助,我想我会分享我的代码以防其他人也遇到一些问题。
private void Playlist_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Copy;
}
private void Playlist_DragDrop(object sender, DragEventArgs e)
{
//get the file names
string[] songs = (string[])e.Data.GetData(DataFormats.FileDrop, false);
//we're using a Parallel.ForEach loop because if a directory is selected it can contain n number of items, this is to help prevent a bottleneck.
Parallel.ForEach(songs, song =>
{
//make sure the file exists
if (File.Exists(song))
{
//if it's an mp3 file then call AddFileToListview
if (string.Compare(Path.GetExtension(song), ".mp3", true) == 0)
{
AddFileToListview(song);
}
}
//A HA! It's a directory not a single file
else if (Directory.Exists(song))
{
//get the directory information
DirectoryInfo di = new DirectoryInfo(song);
//get all the mp3 files (will add WMA in the future)
FileInfo[] files = di.GetFiles("*.mp3");
//here we use a parallel loop to loop through every mp3 in the
//directory provided
Parallel.ForEach(files, file =>
{
AddFileToListview(file.FullName);
});
}
});
}
private void AddFileToListview(string fullFilePath)
{
double nanoseconds;
string totalTime = string.Empty;
//First things first, does the file even exist, if not then exit
if (!File.Exists(fullFilePath))
return;
//get the song name
string song = Path.GetFileName(fullFilePath);
//get the directory
string directory = Path.GetDirectoryName(fullFilePath);
//hack off the trailing \
if (directory.EndsWith(Convert.ToString(Path.DirectorySeparatorChar)))
directory = directory.Substring(0, directory.Length - 1);
//now we use the WindowsAPICodePack.Shell to start calculating the songs time
ShellFile shell = ShellFile.FromFilePath(fullFilePath);
//get the length is nanoseconds
double.TryParse(shell.Properties.System.Media.Duration.Value.ToString(), out nanoseconds);
//first make sure we have a value greater than zero
if (nanoseconds > 0)
{
// double milliseconds = nanoseconds * 0.000001;
TimeSpan time = TimeSpan.FromSeconds(Utilities.ConvertToMilliseconds(nanoseconds) / 1000);
totalTime = time.ToString(@"m\:ss");
}
//build oour song data
ListViewItem item = new ListViewItem();
item.Text = song;
item.SubItems.Add(totalTime);
//now my first run at this gave me a cross-thread exception when trying to add multiple single mp3's
//but I could add all the whole directories I wanted, o that is why we are now using BeginINvoke to access the ListView
if (Playlist.InvokeRequired)
Playlist.BeginInvoke(new MethodInvoker(() => Playlist.Items.Add(item)));
else
Playlist.Items.Add(item);
}
此代码使用 WindowsAPICodePack 来计算每首歌曲的时间。