在 WinForms 應用中實現類似檔案總管的拖放體驗,包含從外部拖入檔案到應用程式與從應用程式拖出檔案到外部。本文提供逐步實作指南與完整程式碼。
ListView (listViewFolder) 並設定:View = View.Details、AllowDrop = true。Label (labelCurFolder) 顯示目前資料夾路徑。private void ListFolder(string directory)
{
labelCurFolder.Text = directory;
listViewFolder.Items.Clear();
listViewFolder.Columns.Clear();
listViewFolder.Columns.Add("Name", 300);
listViewFolder.Columns.Add("Size", 100);
listViewFolder.Columns.Add("Time", 200);
string[] files = Directory.GetFiles(directory);
foreach (string file in files)
{
var item = new ListViewItem(Path.GetFileName(file));
item.Tag = file; // 存儲完整路徑供拖放使用
// 圖示處理 (略,可使用 Icon.ExtractAssociatedIcon)
// item.ImageIndex = ...
FileInfo fi = new FileInfo(file);
item.SubItems.Add(FormatFileSize(fi.Length));
item.SubItems.Add(fi.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss"));
listViewFolder.Items.Add(item);
}
}
private string FormatFileSize(long bytes)
{
if (bytes < 1024) return $"{bytes} B";
if (bytes < 1024 * 1024) return $"{bytes / 1024.0:F1} KB";
if (bytes < 1024 * 1024 * 1024) return $"{bytes / (1024.0 * 1024):F1} MB";
return $"{bytes / (1024.0 * 1024 * 1024):F1} GB";
}
private void listViewFolder_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Copy;
else
e.Effect = DragDropEffects.None;
}
private void listViewFolder_DragDrop(object sender, DragEventArgs e)
{
try
{
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
string targetDir = labelCurFolder.Text;
foreach (string src in files)
{
string dest = Path.Combine(targetDir, Path.GetFileName(src));
if (File.Exists(dest))
{
var result = MessageBox.Show(
$"檔案 {Path.GetFileName(src)} 已存在,是否取代?",
"確認取代", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result != DialogResult.Yes) continue;
}
File.Copy(src, dest, true);
}
ListFolder(targetDir); // 重新整理列表
}
catch (Exception ex)
{
MessageBox.Show($"拷貝失敗: {ex.Message}", "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void listViewFolder_ItemDrag(object sender, ItemDragEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
if (listViewFolder.SelectedItems.Count == 0) return;
// 收集選取項目的完整路徑
string[] files = new string[listViewFolder.SelectedItems.Count];
for (int i = 0; i < files.Length; i++)
files[i] = listViewFolder.SelectedItems[i].Tag.ToString();
// 建立 DataObject 並啟動拖放
DataObject data = new DataObject(DataFormats.FileDrop, files);
data.SetData(DataFormats.StringFormat, files[0]); // 兼容僅支援文字的目標
DoDragDrop(data, DragDropEffects.Copy);
}
listViewFolder.DragEnter += listViewFolder_DragEnter;
listViewFolder.DragDrop += listViewFolder_DragDrop;
listViewFolder.ItemDrag += listViewFolder_ItemDrag;
e.Effect 決定游標樣式。MouseDown + DoDragDrop。