Windowsでお馴染みのドラッグ&ドロップは超便利なので、自作プログラムに組み込みたくなるものですが、イベント処理を記述しなければならないため、結構面倒です。
他のサイトではドラッグ&ドロップの原理とか、イベント処理をゴリゴリ記述するようなサンプルが多いので、本サイトでは瞬殺で実装できるよう関数化しました。
いちいちイベントハンドラを記述しなくても簡単に実装できますので、是非ご活用ください。
尚、WindowsForm版については、こちらの記事で紹介しています。
ドラッグ & ドロップの動作
次の動画を見て頂いた通り、「テキストファイル.txt」というファイルを、目的とするコントロールにドラッグ&ドロップすると、マウスのアイコンが「ドラッグ&ドロップ」用のアイコンに変わっていますね。
つまり、ドロップ先のコントロールは、ドラッグされたファイルを受け付ける状態になっているという事です。
ドロップ後の処理は特に書いていないので画面上何も起こりませんが、「アイコンが変わった=受付状態にある」という所がポイントです。
ドラッグ & ドロップ機能をコントロールに付与するコード
冒頭で説明した通り、ドラッグ&ドロップの機能を任意のコントロールに付与する関数を作りました。
詳細の説明は後回しにして、ここでは使い方と付与するコードの中身を紹介しておきます。
使い方
使い方は簡単で、EnableDragDropという関数の引数にコントロールを渡すだけです。
この関数を呼び出すと、引数で渡したコントロールがドラッグ&ドロップを受け付けるようになるので、コンストラクタか フォームのLoadedイベントハンドラに記述するのが良いかと思います。
1 2 3 4 5 6 |
public MainWindow() { InitializeComponent(); EnableDragDrop(uxComboBox); } |
ソースコード
ソースコードは次の通りです。
Visual Studio でイベントハンドラを作成し、必要な処理をイベントハンドラ内に記述していく必要があるのですが、それを全て関数内で行っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
private void EnableDragDrop(Control control) { //ドラッグ&ドロップを受け付けられるようにする control.AllowDrop = true; //ドラッグが開始された時のイベント処理(マウスカーソルをドラッグ中のアイコンに変更) control.PreviewDragOver += (s, e) => { //ファイルがドラッグされたとき、カーソルをドラッグ中のアイコンに変更し、そうでない場合は何もしない。 e.Effects = (e.Data.GetDataPresent(DataFormats.FileDrop)) ? DragDropEffects.Copy : e.Effects = DragDropEffects.None; e.Handled = true; }; //ドラッグ&ドロップが完了した時の処理(ファイル名を取得し、ファイルの中身をTextプロパティに代入) control.PreviewDrop += (s, e) => { if (e.Data.GetDataPresent(DataFormats.FileDrop)) // ドロップされたものがファイルかどうか確認する。 { string[] paths = ((string[])e.Data.GetData(DataFormats.FileDrop)); //-------------------------------------------------------------------- // ここに、ドラッグ&ドロップ受付時の処理を記述する //-------------------------------------------------------------------- } }; } |
ドラッグ&ドロップ後に行いたい処理は「ここに、ドラッグ&ドロップ受付時の処理を記述する」と書いてある部分に記述して下さい。
解説
処理を出来るだけ簡単に済ませるために、PreviewDragOver と PreviewDrop のイベントハンドラを記述しています。
PreviewDragOver は、ファイルやフォルダをコントロール上にドラッグした時に発生するイベントで、e.Effects にDragDropEffects.Copy を設定することで、アイコンの形を変えています。
PreviewDrop はドロップ時に発生するイベントで、GetData(DataFormats.FileDrop) メソッドによりファイル又はフォルダを取得しています。
尚、一度のドラッグ&ドロップで、複数のファイルやフォルダが渡される可能性があるため、GetDataの戻り値は文字列配列になっています。
どのコントロールに対応しているか
この関数は、Control クラスを継承しているものについてドラッグ&ドロップ対応にできます。
具体的には、TextBox、ComboBox、DataGrid、ListBox、TabContorl、TabItem、ListView、TreeViewなどがあります。
サンプルソース一式
次のリンクからプロジェクト一式がダウンロードできます。
【WPF】ドラッグ アンド ドロップ・デモプログラム一式
入力を伴わないコントロールに対応させる
たまに、入力を伴わないコントロール(GridやCanvasなどのコンテナ系コントロール、動画再生で用いるMediaElementコントロール)に対してドラッグ&ドロップしたいケースがあります。
この場合は、EnableDragDrop 関数の第一引数の型を FrameworkElement に変更して下さい。
1 2 3 4 5 |
private void EnableDragDrop(FrameworkElement control) { //~~~以下省略~~~~ } |
FrameworkElement は WPF としての要素の基本的な機能を持ったクラスであり、Control は FrameworkElement を継承した上でUI(操作)系の機能を盛り込んでいます。
引数の型をFrameworkElementにしておけば、TextBoxやComboBoxなどの入力系と、GridやCanvasなどのコンテナ系のコントロールを両方がサポートされるようになります。
まとめ
今回はWPFのWindowアプリに、ドラッグ&ドロップを組み込む関数を紹介しました。
関数をコピー&ペーストし、コンストラクタか フォームのLoaded イベントで EnableDragDrop を呼び出すだけという手軽さです。
コントロール毎にドラッグ&ドロップのイベントハンドラを書くのは手間なので、関数化しておけば非常に楽になります。
是非ご活用下さい。
コメント