Перетаскивание файлов WPF на TreeView из проводника Windows - PullRequest
6 голосов
/ 19 сентября 2011

Я пытаюсь создать чрезвычайно простую или, как я думал, программу для перетаскивания файла с рабочего стола / проводника в дерево wpf.

Вид дерева в этом примере прост, так что яможет изолировать проблему перетаскивания у меня есть.Я установил AllowDrop равным True везде, я все еще не могу получить события Drop или DragOver для запуска.Я сосредоточен на древовидном управлении, потому что хочу перетаскивать файлы в разные узлы с иерархической структурой. Прямо сейчас я бы согласился на возможность запуска событий DragOver или Drop при перетаскивании файла в древовидное представление.

Я начал с рассмотрения примеров, подобных этому: Перетаскивание в виде дерева

Мой вопрос похож на этот: Перетаскивание файлов из проводника в 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>

edit Я обнаружил, что перетаскивать на панель стека можно только в том случае, если я запускаю проект из смеси выражений.Если я запускаю его из visual studio, он показывает черный круг с линией через него.Это не имеет никакого смысла вообще. Для этой отдельной проблемы я задал здесь еще один вопрос: Проект Visual Studio 2010 WPF, запущенный в режиме отладки или пересылки, не позволит перетаскивать данные на любой элемент управления

Это все из-за запуска Visual Studio в качестве администратора.Очевидно, то же самое верно и для notepad.exe, если вы запускаете что-то от имени администратора, вы не можете перетаскивать.Так что теперь для отладки IIS мне нужно работать от имени администратора, а для перетаскивания мне нужно выяснить, как работать в обычном режиме ...

1 Ответ

1 голос
/ 20 сентября 2011

Я думаю, проблема в том, что вы не перетаскиваете элемент поверх самих 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)
  {

  }
...