7
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[WPF]エクスプローラーからD&Dされたファイルパスを取得する

Posted at

WPFでドラッグ&ドロップを実装するにはコードビハインドやビヘイビアを使用するなどがあるけど、僕はめんどくさがりなのでライブラリを使います。

Nugetにgong-wpf-dragdropがあったのでそれを使います。

今回はエクスプローラーからファイルをD&Dされたcsvファイルのパスを取得し、それをListBoxに表示するMVVMのアプリを作ります。
csvファイル以外は表示しないとします。

View

MainWindow.xaml
<Window x:Class="DragAndDropTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DragAndDropTest"
        xmlns:dd="clr-namespace:GongSolutions.Wpf.DragDrop;assembly=GongSolutions.Wpf.DragDrop"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <Grid>
        <ListBox ItemsSource="{Binding Files}" 
                 dd:DragDrop.IsDropTarget="True" 
                 dd:DragDrop.DropHandler="{Binding}" />
    </Grid>
</Window>

GongSolutions.WPF.DragDrop を使用するにはまずxamlに名前空間を追加します。

xmlns:dd="clr-namespace:GongSolutions.Wpf.DragDrop;assembly=GongSolutions.Wpf.DragDrop"

そして、D&Dを行いたい要素で

<ListBox ItemsSource="{Binding Files}" 
         dd:DragDrop.IsDropTarget="True" 
         dd:DragDrop.DropHandler="{Binding}" />

と記述します。

  • DragDrop.IsDropTarget : ドロップ先のターゲット
  • DragDrop.DropHandler : ドロップイベントのハンドラ

を表しています。今回はドロップされるだけなのでターゲットのみ宣言します。DropHandlerについては後ほど詳細を書きます。

ViewModel

MainWindowViewModel
using GongSolutions.Wpf.DragDrop;
using System.Windows;
using System.Linq;
using System.IO;
using System.Collections.ObjectModel;

namespace DragAndDropTest
{
    public class MainWindowViewModel : IDropTarget
    {
        public ObservableCollection<string> Files { get; set; }

        public MainWindowViewModel()
        {
            Files = new ObservableCollection<string>();
        }

        public void DragOver(IDropInfo dropInfo)
        {
            var dragFileList = ((DataObject)dropInfo.Data).GetFileDropList().Cast<string>();
            dropInfo.Effects = dragFileList.Any(_ =>
            {
                return IsCsv(_);
            }) ? DragDropEffects.Copy : DragDropEffects.None;
        }

        public void Drop(IDropInfo dropInfo)
        {
            var dragFileList = ((DataObject)dropInfo.Data).GetFileDropList().Cast<string>();
            dropInfo.Effects = dragFileList.Any(_ =>
            {
                return IsCsv(_);
            }) ? DragDropEffects.Copy : DragDropEffects.None;

            foreach(var file in dragFileList)
            {
                if (IsCsv(file))
                {
                    Files.Add(file);
                }
            }
        }

        private bool IsCsv(string data)
        {
            var extension = Path.GetExtension(data);
            return extension != null && extension == ".csv";
        }
    }
}

IDropTargetがDropHandlerを実装するためのインターフェースです。DragOver() と Drop() を実装します。
今回はcsvファイルのみ受け付けるため、csvファイルかを判定する IsCsv() を実装しています。

まずDragOver()でcsvファイルがあれば受け付けるようにします。

var dragFileList = ((DataObject)dropInfo.Data).GetFileDropList().Cast<string>();
dropInfo.Effects = dragFileList.Any(_ =>
{
    return IsCsv(_);
}) ? DragDropEffects.Copy : DragDropEffects.None;

GetFileDropList() でドロップされたファイルを取得しています。
そして、IsCsv()がtrueの時にDragDropEffectsがCopy(受け付ける)になり、falseの時にNone(受け付けない)にしています。

次にDrop()も同様にcsvファイルがあれば受け付けるようにし、foreach()内でIsCsv()を呼び、csvファイルでFiles.Add()でcsvファイルパスを追加すればListBoxにファイルパスが表示されます。

スクショ.png

これでD&Dが簡単に実装できました。

7
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?