Winforms C# .NET Framework 同Grid拖拽文件重复问题如何解决
网格控件拖拽重复复制问题修复方案
问题根因
- 现有逻辑未区分拖拽数据来源,只要识别到文件拖放格式就会执行添加逻辑,从自身控件发起的拖拽再放回时也会触发新增
File.Exists(file)校验逻辑完全无效:你要规避的是网格内附件条目的重复,而非磁盘文件重复,拖入的文件本身在磁盘上就是存在的,所以这个判断不会起到拦截作用
修复步骤
1. 拖拽发起时增加自定义来源标记
在MouseDown事件中给拖拽数据对象添加自定义格式标记,标识本次拖拽来自当前网格控件
2. 拖入校验时拦截自身来源的拖拽
在DragEnter事件中识别到自身发起的拖拽时,直接禁用拖放效果,不会触发后续Drop逻辑
3. Drop逻辑增加条目重复校验(双重保险)
即使前面的校验漏过,Drop时先校验当前网格已有的附件列表中是否存在对应文件,不存在才执行添加操作
完整修改后代码
_attachmentGrid.DragEnter += (s, e) => { // 优先判断是否是自身发起的拖拽,直接拦截 if (e.Data.GetDataPresent("Custom_AttachmentGrid_SelfSource")) { e.Effect = DragDropEffects.None; return; } if (e.Data.GetDataPresent(DataFormats.FileDrop)) { e.Effect = DragDropEffects.Copy; } else { e.Effect = DragDropEffects.None; } }; _attachmentGrid.DragDrop += (s, e) => { string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); if (files == null || files.Length == 0) return; // 取当前网格已绑定的附件列表,这里替换成你实际的数据源获取逻辑 var existAttachments = _attachmentGrid.DataSource as List<你的附件实体类型>; foreach (string file in files) { string fileName = Path.GetFileName(file); // 校验当前列表中是否已存在同路径/同名的附件,不存在才添加 if (!existAttachments.Any(x => x.FileAttachment.AttachmentName == fileName)) { AttachFile(file); } } }; _attachmentGrid.MouseDown += (s, e) => { byte[] data = GetData(_selection.SingleSelection); string fileName = _selection.SingleSelection.Entity.FileAttachment.AttachmentName; var list = new StringCollection(); list = _manager.DragAttachment(data, fileName); DataObject dataObject = new DataObject(); dataObject.SetFileDropList(list); // 新增自定义来源标记 dataObject.SetData("Custom_AttachmentGrid_SelfSource", true); _attachmentGrid.DoDragDrop(dataObject, DragDropEffects.Move | DragDropEffects.Copy); };
补充说明
如果后续需要支持控件内部拖拽排序,只需要修改DragEnter的判断逻辑,自身来源时把Effect改成DragDropEffects.Move,然后在DragDrop中单独处理内部排序逻辑,不要调用AttachFile新增条目即可。
内容的提问来源于stack exchange,提问作者Otto
相关产品推荐
相关产品推荐

