【问题标题】:WPF drag and drop files onto TreeView from windows explorerWPF 从 Windows 资源管理器拖放文件到 TreeView
【发布时间】:2011-09-19 19:49:18
【问题描述】:

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

此示例中的树视图很简单,因此我可以隔离我遇到的拖放问题。我已经在各处设置 AllowDrop 等于 True,我仍然无法触发 Drop 或 DragOver 事件。我专注于树视图控件,因为我希望能够将文件拖到具有层次结构的不同节点中。 现在,当我将文件拖到树视图上时,我只需要能够触发 DragOver 或 Drop 事件。

我是从以下示例开始的:Drag & Drop in Treeview

我的问题与此类似:Drag drop files from explorer onto Telerik WPF treeview。但是我使用的是 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 Project ran in debug or relase will not allow drag and drop to any control

这都是因为以管理员身份运行 Visual Studio。 notepad.exe 显然也是如此,如果您以管理员身份运行某些内容,则无法拖放。因此,现在对于 IIS 调试,我必须以管理员身份运行,对于拖放,我需要弄清楚如何在正常模式下运行......

【问题讨论】:

  • 你觉得如何让它工作?你在 TreeView1_Drop 里面有问题吗?如果是这样,请解释您需要什么并展示您尝试过的内容,开始检查 DragEventArgs e 对象的属性,并在调试时查看它包含的内容以及如何使用它来获得所需的内容。对于您留空的其他事件也是如此...
  • 我已将问题中表示问题在于事件未触发的部分加粗。谢谢。
  • 你是否将drop的accept item变量设置为true?

标签: c# wpf treeview wpf-controls


【解决方案1】:

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

使用此解决方案您将遇到的问题是 TreeView 事件将首先触发。所以现在你必须知道你结束了哪个节点才能正确添加它。有一些解决方案可以确定您结束了哪个节点。但是,我建议向您的树添加一个始终存在的顶级元素。然后像你一样将事件连接到 TreeViewItems。这样,您可以在顶层添加,而无需处理 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)
  {

  }

【讨论】:

  • 我已经编辑了这个问题,专注于让事件在树视图上触发。我将事件重新连接到树视图,并摆脱了树视图项上的事件设置器。必须有一些非常简单的东西我错过了。当我将文件拖到树视图上时,我得到的只是一个黑色圆圈,其中有一条线。释放文件似乎不会触发 Drop 事件。如果我能让那个事件触发,我就可以进行命中测试,或者找出它结束的节点。
  • 我让它在表达式混合中工作,但是当我在 Visual Studio 中使用最新的 xaml 时,它不会让我拖放到树视图内的堆栈面板上。我真的充满希望,因为如果我可以让堆栈面板拖放,这将启动这个项目。
  • 我将您的答案标记为答案,因为它让我想到,我的电脑出了点问题。这导致我发现如果您以管理员身份运行,则无法拖放。
猜你喜欢
  • 1970-01-01
  • 2011-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多