WPF从windows资源管理器中拖放文件到TreeView

本文关键字:文件 TreeView 拖放 windows 资源管理器 WPF | 更新日期: 2023-09-27 18:09:07

我正在尝试制作一个非常简单的程序,或者我认为,将文件从桌面/资源管理器拖放到wpf树视图上。

这个例子中的树视图很简单,所以我可以隔离我所遇到的拖放问题。我在各处都设置了AllowDrop = True,我仍然不能让Drop或DragOver事件触发。我专注于treeview控件,因为我希望能够将文件拖动到具有分层结构的不同节点中。现在,当我把文件拖到树视图上时,我只想让拖过或拖放事件触发。

我已经开始看这样的例子:Drop in Treeview

我的问题类似于这个:从资源管理器拖放文件到Telerik WPF树视图。但是我使用的是wpf树视图,而不是telerik树视图。

这是我到目前为止写的代码

XAML:

   <Window x:Class="WpfDragAndDropTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfDragAndDropTest"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TreeView Name="TreeView1">
            <TreeView.ItemContainerStyle>
                <Style TargetType="{x:Type TreeViewItem}" >
                    <Setter Property="TreeViewItem.AllowDrop" Value="True"/>
                    <EventSetter Event="TreeViewItem.DragOver" Handler="TreeView1_DragOver" />
                    <EventSetter Event="TreeViewItem.Drop" Handler="TreeView1_Drop" />
                    <EventSetter Event="TreeViewItem.MouseMove" Handler="TreeView1_MouseMove" />
                </Style>
            </TreeView.ItemContainerStyle>
            <TreeView.Resources>
                <DataTemplate DataType="{x:Type local:TestClass}">
                    <StackPanel Orientation="Vertical"  >
                        <TextBlock Text="{Binding Path=Title}" />
                        <TextBlock Text="{Binding Path=Url}" />
                    </StackPanel>
                </DataTemplate>
            </TreeView.Resources>
        </TreeView>
    </Grid>
    </Window>
代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfDragAndDropTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        TreeView1.ItemsSource = new[] 
        { 
            new TestClass { Title = "Google", Url = "http://www.google.com" }, 
            new TestClass { Title = "Microsoft", Url = "http://www.microsoft.com" },
            new TestClass{ Title="Netflix", Url="http://www.netflix.com" }
        };
    }
    private void TreeView1_Drop(object sender, DragEventArgs e)
    {
    }
    private void TreeView1_DragOver(object sender, DragEventArgs e)
    {
    }
    private void TreeView1_MouseMove(object sender, MouseEventArgs e)
    {
    }
}

public class TestClass
{
    public string Title { get; set; }
    public string Url { get; set; }
}
}

编辑我把说明问题的文本保留为事件未触发。

我把我的xaml切换到这个,我仍然得到一个黑色的圆圈,当把文件拖过树视图时,它有一条线,唯一触发的事件是MouseMove。如果我使用鼠标来执行这些操作,则拖放不会触发。

    <TreeView Name="TreeView1" AllowDrop="True" DragOver="TreeView1_DragOver" Drop="TreeView1_Drop" MouseMove="TreeView1_MouseMove">

        <TreeView.Resources>
            <DataTemplate DataType="{x:Type local:TestClass}">
                <StackPanel Orientation="Vertical"  >
                    <TextBlock Text="{Binding Path=Title}" />
                    <TextBlock Text="{Binding Path=Url}" />
                </StackPanel>
            </DataTemplate>
        </TreeView.Resources>
    </TreeView>

编辑我尝试了一个空白的树视图,可以在上面拖动文件,但光标不是黑色的圆圈,其中有一行穿过它。

<TreeView Height="312" Background="#FFCFDBF9" AllowDrop="True"/>

然而,当DataTemplate被添加到它,那是当黑色圆圈开始显示。这一定是数据绑定的问题吧?

编辑我现在开始有所进展了。

我把我的xaml改成这个,事件开始触发:

<TreeView Name="TreeView1" Background="#FFC9D7FF">

    <TreeView.Resources>
        <DataTemplate DataType="{x:Type local:TestClass}">
            <StackPanel Orientation="Vertical"  AllowDrop="True" DragOver="TreeView1_DragOver" Drop="TreeView1_Drop" MouseMove="TreeView1_MouseMove" >
                <TextBlock Text="{Binding Path=Title}" />
                <TextBlock Text="{Binding Path=Url}" />
            </StackPanel>
        </DataTemplate>
    </TreeView.Resources>
</TreeView>

编辑我发现,如果我从表达式混合中运行项目,我只能拖拽到堆栈面板。如果我在visual studio中运行它会显示一个黑色圆圈,中间有一条线。这完全说不通啊。对于这个单独的问题,我在这里开始了另一个问题: Visual Studio 2010 WPF项目在调试或发布中运行将不允许拖放任何控件

这都是由于以管理员身份运行visual studio。显然,对于notepad.exe也是如此,如果你以管理员身份运行某些东西,你不能拖放。所以现在对于IIS调试,我必须以管理员身份运行,对于拖放,我需要弄清楚如何在正常模式下运行…

WPF从windows资源管理器中拖放文件到TreeView

我认为问题是你没有将项目拖过TreeViewItems本身。这是必要的,因为您的事件仅为TreeViewItems注册。如果要拖放到树的父级,则需要将相应的事件添加到树中。

这个解决方案的问题是TreeView事件将首先触发。所以现在你必须知道你在哪个节点上才能正确地添加它。有一些解决方案可以确定您在哪个节点上。但是,我建议在树中添加一个始终存在的顶级元素。然后像你一样将事件连接到treeviewitem。这样,你就可以在顶层添加,而不必处理TreeView事件,因为你可以将项目拖到顶层。

下面是我用来测试的,如果我直接拖过TreeViewItems,我可以看到断点。您可能不认识某些名称空间,但这是因为它引用了我的项目。

XAML:

  <TreeView x:Name="treeView">
     <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}" >
           <Setter Property="TreeViewItem.AllowDrop" Value="True"/>
           <EventSetter Event="TreeViewItem.DragOver" Handler="treeView_DragOver" />
           <EventSetter Event="TreeViewItem.Drop" Handler="treeView_Drop" />
           <EventSetter Event="TreeViewItem.MouseMove" Handler="treeView_MouseMove" />
        </Style>
     </TreeView.ItemContainerStyle>
     <TreeView.Resources>
        <DataTemplate DataType="{x:Type FileExplorerDragDrop:TestClass}">
           <StackPanel Orientation="Vertical"  >
              <TextBlock Text="{Binding Path=Title}" />
              <TextBlock Text="{Binding Path=Url}" />
           </StackPanel>
        </DataTemplate>
     </TreeView.Resources>
  </TreeView>  

代码:

  public MainWindow()
  {
     InitializeComponent();
     treeView.ItemsSource = new[] 
     { 
        new TestClass { Title = "Google", Url = "http://www.google.com" }, 
        new TestClass { Title = "Microsoft", Url = "http://www.microsoft.com" },
        new TestClass{ Title="Netflix", Url="http://www.netflix.com" }
     };
  }
  private void treeViewItem_DragOver(object sender, DragEventArgs e)
  {
  }
  private void treeViewItem_Drop(object sender, DragEventArgs e)
  {
  }
  private void treeViewItem_MouseMove(object sender, MouseEventArgs e)
  {
  }