WPF+MVVMでドラッグ&ドロップの実装

More than 1 year has passed since last update.


はじめに

WPF+MVVMでリストにドラッグ&ドロップを実装するための方法です。


方法

実装にあたっては、MVVMの作法に則るために、コードビハインド(xaml.cs)には何も書きたくありません。

このためには、GongSolutions.WPF.DragDropを利用するのが楽です。

これはNugetからインストールすることもできます。


使い方


View側

まず、xamlの名前空間に下記を追加します。


SampleWindow.xaml

xmlns:dd="urn:gong-wpf-dragdrop"


さらに、ドラッグアンドドロップをしたい ListBox などに対して、次のプロパティを追加します。


SampleWindow.xaml

<ListBox ItemsSource="{Binding Files}" 

dd:DragDrop.IsDropTarget="True"
dd:DragDrop.DropHandler="{Binding}"/>


  • 注意



    • Files は、ViewModelの定義に応じて適切なプロパティ名に変更する


    • DropHandler="{Binding}" は、DropHandler に現在の DataContext をバインドするという意味




ViewModel側

ViewModel では GongSolutions.Wpf.DragDrop.IDropTarget インターフェースを実装すればOKです。

下記の例では、リストにzipファイルのパスを列挙する機能を実装しています。


SampleWindowViewModel.cs

using GongSolutions.Wpf.DragDrop;

using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;

class SampleWindowViewModel : IDropTarget
{
public ObservableCollection<string> Files { get; } = new ObservableCollection<string>();

public void DragOver(IDropInfo dropInfo)
{
var files = ((DataObject)dropInfo.Data).GetFileDropList().Cast<string>();
dropInfo.Effects = files.Any(fname => fname.EndsWith(".zip"))
? DragDropEffects.Copy : DragDropEffects.None;
}

public void Drop(IDropInfo dropInfo)
{
var files = ((DataObject)dropInfo.Data).GetFileDropList().Cast<string>()
.Where(fname => fname.EndsWith(".zip")).ToList();

if (files.Count == 0) return;

foreach (var file in files)
Files.Add(file);
}
}



  • 注意



    • IDropTargetSystem.Windows.Forms にも同名のインターフェースが存在するため、参照先を間違えないようにする


    • DragOver はドラッグした状態でリストにマウスオーバーしたときに実行されるメソッド


    • DropDragOver 状態でマウスボタンを離したときに実行されるメソッド



以上で、ドラッグ&ドロップ機能を持つ ListBox の実装が完了しました。


まとめ

GongSolutions.WPF.DragDropを利用すれば、MVVMの作法で簡単にドラッグ&ドロップを実装できます。