執筆者: 大野 元久

動作確認環境: Visual Studio 2008、Visual Studio 2010

更新日: 2010 年 11 月 26 日

Windows フォームでは、ドラッグ アンド ドロップはコントロールの機能の一部として実装されていましたが、WPF では DragDrop というクラスで実装されています。両者の使い方に、それほど大きな違いはありませんが、いくつか注意すべき点があります。

Code [XAML]

<Window x:Class="WpfDragDropApplication.MainWindow"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="MainWindow" Height="300" Width="400">
   <TabControl>
       <TabItem Header="TextBox">
           <DockPanel>
               <!-- テキストボックスどうしでドラッグ アンド ドロップ -->
               <TextBox DockPanel.Dock="Top" Name="tbox1" Height="100"
                        Text="Sample Text"/>
               <TextBox DockPanel.Dock="Top" Name="tbox2"
                        Text="Test String"/>
           </DockPanel>
       </TabItem>
       <TabItem Header="Labels">
           <StackPanel Orientation="Horizontal">
               <!-- ラベルどうしでドラッグ アンド ドロップ -->
               <Label DockPanel.Dock="Left" Name="lable1" Content="Item1" AllowDrop="True"
                      MouseDown="lable_MouseDown" DragOver="label_DragOver" Drop="label_Drop" />
               <Label DockPanel.Dock="Left" Name="lable2" Content="Item2" AllowDrop="True"
                      MouseDown="lable_MouseDown" DragOver="label_DragOver" Drop="label_Drop" />
               <Label DockPanel.Dock="Left" Name="lable3" Content="Item3" AllowDrop="True"
                      MouseDown="lable_MouseDown" DragOver="label_DragOver" Drop="label_Drop" />
           </StackPanel>
       </TabItem>
       <TabItem Header="FileDrop">
           <!-- エクスプローラーからテキストファイルをドロップできる -->
           <TextBox Name="tbox3" TextWrapping="Wrap"
                    PreviewDragOver="tbox3_PreviewDragOver" Drop="tbox3_Drop" />
       </TabItem>
   </TabControl>
</Window>

Code [C#]

……
using System.IO;

namespace WpfDragDropApplication
{
   /// <summary>
   /// MainWindow.xaml の相互作用ロジック
   /// </summary>
   public partial class MainWindow : Window
   {
       public MainWindow()
       {
           InitializeComponent();
       }

       private void lable_MouseDown(object sender, MouseButtonEventArgs e)
       {
           // ドラッグ アンド ドロップを開始する
           DragDrop.DoDragDrop(sender as Label, (sender as Label).Content.ToString(), DragDropEffects.Copy);
       }

       private void label_DragOver(object sender, DragEventArgs e)
       {
           // ドラッグされているものがテキストの場合だけ受け入れる
           if (e.Data.GetDataPresent(DataFormats.Text))
               e.Effects = DragDropEffects.Copy;
       }

       private void label_Drop(object sender, DragEventArgs e)
       {
           // ドロップされたテキストを Content に割り当て
           (sender as Label).Content = e.Data.GetData(DataFormats.Text);
       }

       private void tbox3_PreviewDragOver(object sender, DragEventArgs e)
       {
           // ファイルをドロップされた場合のみ e.Handled を True にする
           e.Handled = e.Data.GetDataPresent(DataFormats.FileDrop);
       }

       private void tbox3_Drop(object sender, DragEventArgs e)
       {
           string[] files = e.Data.GetData(DataFormats.FileDrop) as string[];
           if (files != null)
           {
               // 最初のファイルを SJIS テキストとして読み込む
               using (var reader = new StreamReader(files[0], Encoding.GetEncoding("SJIS")))
                   tbox3.Text = reader.ReadToEnd();
           }
       }
   }
}

実行結果

ポイント

まず、WPF では TextBox や RichTextBox コントロールに、あらかじめテキストをドラッグ アンド ドロップする機能が組み込まれています。このため、TextBox コントロールについては、とくにプログラムを書かなくても、コントロール間のドラッグ アンド ドロップが使えるようになります (左図、「TextBox」タブ)。

通常のコントロールでは、マウスの左ボタンを押した時点 (MouseDown イベント) で DoDragDrop メソッドを呼び出してドラッグを開始し、AllowDrop プロパティが True に設定されているコントロールで、ドロップを受け入れます。受け入れるコントロールは DragOver イベント ハンドラーで、e.Handled プロパティを true に設定します (右図、「Labels」タブ)。なお、WPF では DoDragDrop メソッドは、コントロール クラスではなく、DragDrop クラスのメソッドであり、ドラッグ アンド ドロップの発生元を第 1 引数として渡す必要があります。

Windows フォームと WPF の、プロパティやイベントの対応について以下の表に示します (同じ名前のものでも定義されている場所や意味が少しずつ異なります)。

Windows フォーム WPF 説明
AllowDrop AllowDrop ドラッグ アンド ドロップを受け入れるプロパティ。
  PreviewDragEnter ドラッグされてきたことを示すイベント。(前処理)
DragEnter DragEnter ドラッグされてきたことを示すイベント。
  PreviewDragOver ドラッグ中であることを示すイベント。(前処理)
DragOver DragOver ドラッグ中であることを示すイベント。
  PreviewDragLeave ドラッグが離れたことを示すイベント。(前処理)
DragLeave DragLeave ドラッグが離れたことを示すイベント。
  PreviewDrop ドラッグされたことを示すイベント。(前処理)
DragDrop Drop ドラッグされたことを示すイベント。
DoDragDrop DragDrop.DoDragDrop ドラッグを開始するメソッド。
DragEventArgs DragEventArgs イベント ハンドラーの第 2 引数の型。

Windows エクスプローラーからファイル名をドラッグ アンド ドロップする場合も同じようにプログラムできます(「FileDrop」タブ)。この場合は、DragOver イベント ハンドラーの第 2 引数 (DragEventArgs 型) の Data.GetDataPresent で DataFormats.FileDrop 型のデータがあるかどうかを確認します。

なお、TextBox コントロールでは既定でテキストのドラッグ アンド ドロップのコードが組み込まれているため、DragOver イベントではなく、前処理として発生する PreviewDragOver イベントを使っています。

ドラッグ アンド ドロップの詳細については「ドラッグ アンド ドロップの概要」を参照してください。


Code Recipe Code Recipe

ページのトップへ