【问题标题】:WPF: Drag and drop virtual files into Windows explorerWPF:将虚拟文件拖放到 Windows 资源管理器中
【发布时间】:2011-06-19 04:09:59
【问题描述】:

我正在开发一个类似于 dropbox 的应用程序,并在 WPF 列表视图中显示远程文件。我想将这些元素拖放到 Windows 资源管理器中。 我见过这样的代码:

var dataObject = new DataObject(DataFormats.FileDrop, files.ToArray());
dataObject.SetData(DataFormats.StringFormat, dataObject);
DoDragDrop(dataObject, DragDropEffects.Copy);

但您可能认为,这些文件尚未在本地系统中,在复制它们之前,我需要连接到服务器,下载并解压缩文件。就像 ftp 客户端一样。

我不知道该怎么做,但我想知道是否有任何“丢弃”事件或类似的我可以处理。

谢谢!

【问题讨论】:

    标签: c# wpf drag-and-drop


    【解决方案1】:

    这个sn-p:

    var virtualFileDataObject = new VirtualFileDataObject(
                    // BeginInvoke ensures UI operations happen on the right thread
                    (vfdo) => Dispatcher.BeginInvoke((Action)(() => BusyScreen.Visibility = Visibility.Visible)),
                    (vfdo) => Dispatcher.BeginInvoke((Action)(() => BusyScreen.Visibility = Visibility.Collapsed)));
    
                // Provide a virtual file (downloaded on demand), its URL, and descriptive text
                virtualFileDataObject.SetData(new VirtualFileDataObject.FileDescriptor[]
                {
                    new VirtualFileDataObject.FileDescriptor
                    {
                        Name = "DelaysBlog.xml",
                        StreamContents = stream =>
                            {
                                using(var webClient = new WebClient())
                                {
                                    var data = webClient.DownloadData("http://blogs.msdn.com/delay/rss.xml");
                                    stream.Write(data, 0, data.Length);
                                }
                            }
                    },
                });
                virtualFileDataObject.SetData(
                    (short)(DataFormats.GetDataFormat(CFSTR_INETURLA).Id),
                    Encoding.Default.GetBytes("http://blogs.msdn.com/delay/rss.xml\0"));
                virtualFileDataObject.SetData(
                    (short)(DataFormats.GetDataFormat(DataFormats.Text).Id),
                    Encoding.Default.GetBytes("[The RSS feed for Delay's Blog]\0"));
    
                DoDragDropOrClipboardSetDataObject(e.ChangedButton, TextUrl, virtualFileDataObject, DragDropEffects.Copy);
    

    使用类linked 应该可以工作。 .非常好的和简单的解决方案。

    【讨论】:

    • 请概述链接的内容。 Link-only answers are discouraged 因为链接可能会失效。鉴于原始内容已被移动,这在某种程度上已经有了。在旧 URL 下,目前仍有一个指向新 URL 的指针,但谁知道它会在那里保留多久,以及新 URL 上的信息将可用多长时间......
    • 提供答案链接不是答案,也不是 StackOverflow 使用政策中列出的答案所需的质量。请提供正确的答案,我会投票。谢谢-AMR
    【解决方案2】:

    http://pavanpodila.spaces.live.com/blog/cns!9C9E888164859398!190.entry http://pavanpodila.spaces.live.com/blog/cns!9C9E888164859398!199.entry http://pavanpodila.spaces.live.com/blog/cns!9C9E888164859398!225.entry

    请参阅本系列文章。这应该可以帮助您入门。

    编辑:有关 dragsourceadvisor 的补充,请参阅此内容

     internal class ImagesViewPanelDragSourceAdvisor : IDragSourceAdvisor
     {
         private FrameworkElement _dragSource;
    
         public DependencyObject DragSource
         {
             get
             {
                 return _dragSource;
             }
             set
             {
                 _dragSource = value as FrameworkElement;
             }
         }
    
         public DependencyObject DragObject { get; set; }
    
         public DragDropEffects GetDragDropEffects()
         {
             DragDropEffects effects = DragDropEffects.None;
    
             FrameworkElement frameworkObj = DragObject as FrameworkElement;
    
             if (frameworkObj != null && frameworkObj.DataContext is ImageViewModel)
             {
                 effects = DragDropEffects.Copy;
             }
    
             return effects;
         }
    
         public IDataObject GetDragDataObject()
         {
             Debug.Assert(GetDragDropEffects() != DragDropEffects.None);
    
             ImagesViewModel imagesVM = (FrameworkElement)DragSource).DataContext  as ImagesViewModel;
    
             StringCollection fileList = new StringCollection();
    
             foreach (ImageViewModel imageVM in imagesVM.Items.Where(imageVM => imageVM.IsSelected))
             {
                 fileList.Add(imageVM.ImagePath);
             }
    
             Debug.Assert(fileList.Count > 0);
    
             DataObject dataObj = new DataObject();
    
             dataObj.SetFileDropList(fileList);
    
             return dataObj;
         }
    
         public void FinishDrag(DragDropEffects finalEffect)
         {
         }
    

    【讨论】:

    • 这个示例在 UIElements 之间运行良好,但在它们之间运行良好(例如 Windows 桌面)。无论如何,感谢您的帮助。
    • 它可以在桌面和您的应用程序之间进行拖放。您只需要一个适当的 DropTargetAdvisor 类。让我用一个例子来编辑我的答案
    • 很抱歉,在这里解释整个事情的时间太长了。您唯一需要更改的是 DropTargetAdvisor 和 DragSourceAdvisor 的适当实现。您可以做的是在您的应用程序中执行链接的操作,然后在顾问类中放置断点并查看在桌面和您的应用程序之间拖放的内容,然后进行相应的编码。 HTH。
    • 我明白了,但我认为从桌面拖放到具有“允许放置”属性的 wpf 元素比将 wpf 元素拖放到桌面要容易得多。那就是我迷路的地方。感谢您的关注。
    • 我看到你使用“fileList.Add(imageVM.ImagePath);”所以我假设这些图像可以从您的本地系统访问。我的问题是文件实际上不在我的系统中,它们在远程服务器中,所以在将它们复制到我的“资源管理器”之前,我必须执行几个操作。这就是为什么我需要捕获 drop 事件,只是为了知道我必须开始处理远程文件的那一刻。感谢您的努力。
    猜你喜欢
    • 2012-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-01
    • 2015-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多