7

I am trying to make an extremely simple, or so I thought, program to drag and drop a file from the desktop/explorer onto a wpf treeview.

The treeview in this example is simple so that I could isolate the drag and drop problem I am having. I have set AllowDrop equals True all over the place, I still can't get the Drop or DragOver events to fire. I am focused on a treeview control because I want to be able to drag files into different nodes with a hierarchical structure. Right now I would settle for just being able to get the DragOver or Drop events to fire when I drag a file onto the treeview.

I have gotten started by looking at examples such as this: Drag & Drop in Treeview

My question is similiar to this one: Drag drop files from explorer onto Telerik WPF treeview. However I am using the wpf treeview, not the telerik one.

Here is the code I have so far

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>

Code:

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; }
}
}

Edit I bolded the text that spells out my problem as the events not firing.

I switched my xaml to this and I still get a black circle with a line through it when dragging a file over the treeview and the only event that fires is the MouseMove. The Drag and Drop do not fire if I use the mouse to perform those actions.

    <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>

Edit I tried a blank treeview and was able to drag a file over it, and the cursor was not the black circle with the line through it.

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

However when that DataTemplate is added to it, that's when the black circle starts showing up. This must be some kind of databinding issue?

Edit I'm starting to get somewhere now.

I changed my xaml to this and the events start firing:

<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>

edit I have discovered that I can only drag and drop to the stackpanel if I run the project from expression blend. If I run it from visual studio it shows the black circle with a line through it. That doesn't make any sense at all. For this seperate problem I have started another question here: Visual Studio 2010 WPF Project ran in debug or relase will not allow drag and drop to any control

This is all due to running visual studio as administrator. Apparently the same is true for notepad.exe, if you run something as administrator you can't drag and drop. So now for IIS debugging I have to run as administrator and for dragging and dropping I need to figure out how to run in normal mode...

Community
  • 1
  • 1
249076
  • 650
  • 12
  • 22
  • how do you imagine to ever get this working? do you have a problem inside TreeView1_Drop ? if so, explain what you need and show what you tried, start checking the properties of the DragEventArgs e object and see at debug time what it contains and how you can use it to get what you need. same for those other events you left empty... – Davide Piras Sep 19 '11 at 19:59
  • I have bolded the part of the question that says the problem is the events not firing. Thanks. – 249076 Sep 20 '11 at 12:27
  • Are you setting the accept item variable of the drop and drag over to true? – Danny Varod Sep 20 '11 at 13:20

1 Answers1

1

I think the issue is you are not dragging the item over the TreeViewItems themselves. This is necessary because your events are registered for the TreeViewItems only. If you want to drag and drop into a parent level of you tree, you will need to add the corresponding events to your tree.

The issue you will have with this solution is the TreeView events will fire first. So now you're going to have to know which node you're over to add it properly. There are solutions to figure out which node you are over. However, I would suggest adding a top level element to your tree that is always there. Then wire up the events to the TreeViewItems like you are. That way, you can add at a top level without having to handle the TreeView events because you can drag to that top level item.

Below is what I used to test it out and I'm seeing the breakpoints if I drag directly over the TreeViewItems. You may not recognize some namespaces but that's because it's referencing my project.

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>  

Code behind:

  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)
  {

  }
Josh
  • 2,955
  • 1
  • 19
  • 28
  • I have edited the question to focus on just getting the events to fire on the treeview. I rehooked the events to the treeview, and got rid of the event setters on the treeviewitems. There has to be something extremely simple I am missing. When I drag the file over the treeview all I get is a black circle with a line through it. Releasing the file does not seem to cause the Drop Event to fire. If I could get that event to fire I could do hit testing, or something to figure out what node it was over. – 249076 Sep 20 '11 at 12:32
  • I got it working in expression blend, but when I use the latest xaml in visual studio it won't let me drag and drop onto the stack panel inside the treeview. I was really hopefull because if I could get the stack pannel to drag and drop that would kick this project into gear. – 249076 Sep 20 '11 at 13:17
  • I marked yours as the answer because it got me thinking, that something was wrong with my computer. That led to me finding out that you can't drag and drop if your running as administrator. – 249076 Sep 20 '11 at 13:37