更新日: 2010 年 8 月 20 日

Visual Basic の内容はこちらに掲載しています。10 行でズバリ!! [VB] ファイルのドラッグ アンド ドロップ

このコンテンツのポイント

  • ドラッグ アンド ドロップでファイル情報を受け取る
  • ファイル情報を使って、ファイルを読み込んで利用する

今回紹介するコード

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using System.Windows.Media.Imaging;

namespace SampleDropFiles
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();

            textblock1.AllowDrop = true;
            textblock1.Drop += new DragEventHandler(textblock1_Drop);
            textblock1.DragEnter += new DragEventHandler(textblock1_DragEnter);
            textblock1.DragLeave += new DragEventHandler(textblock1_DragLeave);
        }

        private void textblock1_Drop(object sender, DragEventArgs e)
        {
            rectangle1.Fill = new SolidColorBrush(Colors.White);

            if (e.Data == null)
                return;

            IDataObject dataObj = e.Data as IDataObject;
            FileInfo[] files = dataObj.GetData(DataFormats.FileDrop) as FileInfo[];
            listBox1.ItemsSource = files;
        }

        void textblock1_DragEnter(object sender, DragEventArgs e)
        {
            rectangle1.Fill = new SolidColorBrush(Colors.Orange);
        }

        void textblock1_DragLeave(object sender, DragEventArgs e)
        {
            rectangle1.Fill = new SolidColorBrush(Colors.White);
        }
    }
}
 

目次

  1. はじめに
  2. サンプル アプリケーションの作成準備
  3. ユーザー インターフェイスの作成
  4. ドラッグ アンド ドロップでファイル情報を受け取る
  5. ドラッグ中の処理
  6. ドロップされたファイルを利用するための拡張
  7. おわりに

1. はじめに

Silverlight 4 では、Windows エクスプローラーから選んだファイルを、Silverlight アプリケーションにドラッグ アンド ドロップすることで、ファイル情報を受け取ることができます。

ここでは、簡単なアプリケーションを作成して、ドラッグ アンド ドロップのための基本処理と、ファイル操作について解説します。

ページのトップへ


2. サンプル アプリケーションの作成準備

まず、Visual Studio を起動して、[ファイル] メニューの [新規作成] から [プロジェクト] をクリックし、[新しいプロジェクト] を開きます。次に、[インストールされたテンプレート] で [Silverlight] カテゴリーにある [Silverlight アプリケーション] を選びます。[名前] には任意のプロジェクト名を指定できますが、ここでは「SampleDropFiles」とします。

図 1. [新しいプロジェクト] ダイアログで Silverlight アプリケーションのプロジェクトを新規作成

[OK] をクリックすると、[新しい Silverlight アプリケーション] ダイアログが表示され、これから作成する Silverlight アプリケーションが埋め込まれた Web ページを持つ Web サイトを作成するかどうかと、Silverlight のバージョンが確認されます。ここでは、[Silverlight アプリケーションを新しい Web サイトでホストする] のチェックを外します。これで、この Silverlight アプリケーションを実行しようとするたびに、仮の Web サイトが自動作成されます。Silverlight のバージョンは、「Silverlight 4」のままにしておきます。

図 2. [新しい Silverlight アプリケーション] ダイアログ

[OK] ボタンをクリックすると、SampleDropFiles ソリューションと、Silverlight アプリケーションのための SampleDropFiles プロジェクトが作成されます。

図 3. プロジェクト作成直後の Visual Studio 2010

ページのトップへ


3. ユーザー インターフェイスの作成

まず、MainPage.xaml に今回のアプリケーションで使うユーザー インターフェイスを作成します。ここでは、Grid を使って領域を四分割し、左上にはファイル名を一覧表示するためのリスト ボックス (ListBox) を、右上にドロップするコントロール (TextBlock) と、その背景となる Rectangle を置きます。下部は 2 つの領域を合わせて、ファイルの内容を表示するための場所 (ScrollViewer) とします。

<UserControl x:Class="SampleDropFiles.MainPage"
   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"
   mc:Ignorable="d"
   d:DesignHeight="300" d:DesignWidth="400">

   <Grid x:Name="LayoutRoot" Background="White">
       <Grid.ColumnDefinitions>
           <ColumnDefinition Width="*" />
           <ColumnDefinition Width="*" />
       </Grid.ColumnDefinitions>

       <Grid.RowDefinitions>
           <RowDefinition Height="1*" />
           <RowDefinition Height="2*" />
       </Grid.RowDefinitions>
 
       <ListBox Grid.Column="0" Grid.Row="0"
                x:Name="listBox1">
           <ListBox.ItemTemplate>
               <DataTemplate>
                   <StackPanel Orientation="Horizontal">
                       <TextBlock FontSize="16" Text="{Binding Name}" VerticalAlignment="Bottom" />
                       <TextBlock FontSize="12" Text=" ... " VerticalAlignment="Bottom" />
                       <TextBlock FontSize="12" Text="{Binding Length}" VerticalAlignment="Bottom" />
                   </StackPanel>
               </DataTemplate>
           </ListBox.ItemTemplate>
       </ListBox>
 
       <Rectangle Grid.Column="1" Grid.Row="0" x:Name="rectangle1"
                  Stroke="Red" StrokeDashArray="4.0" StrokeThickness="2" />
       <TextBlock Grid.Column="1" Grid.Row="0" x:Name="textblock1"
                  TextAlignment="Center"
                  FontSize="20"
                  Text="ここにファイルをドロップしてください。"
                  TextWrapping="Wrap"
                  />
 
       <ScrollViewer Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1"
                     x:Name="scrollViewer1">
       </ScrollViewer>

   </Grid>
</UserControl>

Visual Studio では、図 4 のように表示されます。

図 4. ユーザー インターフェイスを作成する様子

Note: ここではユーザー インターフェイスを作成するために直接 XAML コードを記述していますが、Visual Studio 2010 では、ツールボックスからデザイナー上にコントロールを配置できます。この場合は、上記のリストで使われているコントロールの名前や、データ テンプレートを使うようにしてください。

ページのトップへ


4. ドラッグ アンド ドロップでファイル情報を受け取る

コントロールがドラッグ アンド ドロップを受け入れるためには、AcceptDrop プロパティを true にします。Windows エクスプローラーなどの外部アプリケーションからファイルがドロップされると、Drop イベントが発生するので、どんなファイルがドロップされたかは Drop イベント ハンドラーで確認できます。

次のプログラムでは、textblock1 コントロールがドラッグ アンド ドロップを受け入れるようにし、イベント ハンドラーの引数 (DragEventArgs 型) からファイル情報を取り出して、listBox1 に割り当てています。

using System.Windows.Shapes;
using System.IO;

namespace SampleDropFiles
{
   public partial class MainPage : UserControl
   {
       public MainPage()
       {
           InitializeComponent();

           textblock1.AllowDrop = true;
           textblock1.Drop += new DragEventHandler(textblock1_Drop);

       }

       private void textblock1_Drop(object sender, DragEventArgs e)
       {
           if (e.Data == null)
               return;
 
           IDataObject dataObj = e.Data as IDataObject;
           FileInfo[] files = dataObj.GetData(DataFormats.FileDrop) as FileInfo[];
           listBox1.ItemsSource = files;
       }

   }
}

ファイルの情報は FileInfo クラスの配列として受け取ることができます。FileInfo は、ひとつのファイルの情報を保持するためのクラスで、リスト ボックス (listBox1) では、それぞれの項目を表示するためにデータ テンプレートを使い、Name プロパティと Length プロパティを横に並べて表示しています。

Note: FileInfo クラスについて、通常の実行では Name、Extention、Length 以外のほとんどのプロパティは、セキュリティ上の理由から、アクセスしようとしてもエラーが発生します。ブラウザー外の実行で昇格された信頼が設定されていれば、これらのプロパティを利用できます。

プログラムを実行して、ファイルをドロップしたようすを図 5 に示します。

図 5. いくつかのファイルを右上にドロップした例

ページのトップへ


5. ドラッグ中の処理

上記では、ファイルをドロップした時点のイベント (Drop) だけを処理していましたが、ファイルをドラッグ中に、コントロール上をマウスで移動するときにも DragEnter (ドラッグしながらコントロール上に移動してきた)、DragLeave (ドラッグしながらコントロールを離れていった) というイベントが発生します。これらのイベントを組み合わせることで、ファイルをドラッグ中にもコントロールの外観などを変更できます。

次のプログラムでは、ファイルをドラッグしたまま textblock1 にマウス カーソルが移動したとき (DragEnter)、およびマウス カーソルが離れたとき (DragLeave) のイベントを処理し、textblock1 の背後に表示されている長方形をオレンジ色または白で塗りつぶしています。また、ファイルをドロップしたとき (Drop) にも、背景を白に戻しています。

   public partial class MainPage : UserControl
   {
       public MainPage()
       {
           InitializeComponent();

           textblock1.AllowDrop = true;
           textblock1.Drop += new DragEventHandler(textblock1_Drop);
           textblock1.DragEnter += new DragEventHandler(textblock1_DragEnter);
           textblock1.DragLeave += new DragEventHandler(textblock1_DragLeave);

       }

       private void textblock1_Drop(object sender, DragEventArgs e)
       {
           rectangle1.Fill = new SolidColorBrush(Colors.White);

           if (e.Data == null)
               return;

           IDataObject dataObj = e.Data as IDataObject;
           FileInfo[] files = dataObj.GetData(DataFormats.FileDrop) as FileInfo[];
           listBox1.ItemsSource = files;
       }

       void textblock1_DragEnter(object sender, DragEventArgs e)
       {
           rectangle1.Fill = new SolidColorBrush(Colors.Orange);
       }
 
       void textblock1_DragLeave(object sender, DragEventArgs e)
       {
           rectangle1.Fill = new SolidColorBrush(Colors.White);
       }
   }

プログラムを実行して、ファイルをドラッグすると、ドラッグする領域の背景がオレンジ色に変わります。

図 6. ドラッグ中の様子

Note: DragEnter、DragLeave イベントにも、Drop イベントと同じように第 2 引数として DragEventArgs 型の引数が渡されますが、DragEnter、DragLeave ではファイル情報を取得できません。

ページのトップへ


6. ドロップされたファイルを利用するための拡張

上記のとおり、ファイルのドラッグ アンド ドロップを受け入れるための処理は簡単です。ここで受け取ったファイル情報をもとに、実際にファイルの内容を表示する処理を追加します。ファイルの情報は、FileInfo オブジェクトとしてリスト ボックスの項目に割り当てられています。したがって、選択中の項目として保持されているオブジェクトを FileInfo として取り出し、それを利用してファイルの内容を読み込むことができます。

次のプログラムでは、ファイルの拡張子が「.txt」か「.log」のときには、ファイルをテキストとして読み込み、TextBlock オブジェクトを生成して、scrollViewer1 のコンテンツとして割り当てています。また、拡張子が「.jpg」か「.png」のときは、Image オブジェクトを生成して、scrollViewer1 のコンテンツとして割り当てています。これら以外の拡張子の場合は、コンテンツに null を代入して何も表示しないようにします。

   public partial class MainPage : UserControl
   {
       public MainPage()
       {
           InitializeComponent();

           textblock1.AllowDrop = true;
           textblock1.Drop += new DragEventHandler(textblock1_Drop);
           textblock1.DragEnter += new DragEventHandler(textblock1_DragEnter);
           textblock1.DragLeave += new DragEventHandler(textblock1_DragLeave);
           listBox1.SelectionChanged += new SelectionChangedEventHandler(listBox1_SelectionChanged);
       }
       ……
       private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
       {
           FileInfo file = listBox1.SelectedItem as FileInfo;
           if (file != null)

           {
               if (file.Extension.Equals(".txt") || file.Extension.Equals(".log"))
               {
                   using (Stream stream = file.OpenRead())
                   {
                       using (var reader = new StreamReader(stream))
                       {
                           var tblock = new TextBlock();
                           tblock.Text = reader.ReadToEnd();
                           tblock.TextWrapping = TextWrapping.Wrap;
                           scrollViewer1.Content = tblock;
                       }
                   }
               }
               else if (file.Extension.Equals(".jpg") || file.Extension.Equals(".png"))
               {
                   using (Stream stream = file.OpenRead())
                   {
                       var bmp = new System.Windows.Media.Imaging.BitmapImage();
                       bmp.SetSource(stream);
                       var img = new Image();
                       img.Stretch = Stretch.None;
                       img.Source = bmp;
                       scrollViewer1.Content = img;
                   }
               }
               else
               {
                   scrollViewer1.Content = null;
               }
           }
       }

   }

このプログラムを実行した様子を図 7 に示します。リスト ボックスでファイル名をクリックするたびに、ファイルが読み込まれます。なお、サイズの大きなファイルの場合には、時間がかかることがあります。また、デフォルト エンコーディング (UTF8) 以外で保存されたテキスト ファイルでは、日本語が正しく表示されません。

図 7. リスト ボックスでファイルを選択すると内容が表示される

ページのトップへ


7. おわりに

ドラッグ アンド ドロップは、一般的なアプリケーションではよく使われる操作ですが、Web アプリケーションでは意外に実装が難しい機能です。この仕組みは Windows Live が提供している無料のオンライン ストレージ サービス SkyDrive でも使われていますのでご参照ください。また、ブラウザー外で実行するアプリケーションでは、信頼されたアプリケーション モードにすることで、より詳細なファイル情報を利用できます。

なお、ドラッグ アンド ドロップを使うためには、いくつかの制限があります。たとえば、Silverlight アプリケーションを「ウィンドウなし」で利用する場合には、ドラッグ アンド ドロップは使えません。詳しくは「Windowless (Silverlight プラグイン オブジェクト)」を参照してください。さらに、Macintosh ではドラッグ アンド ドロップの処理が異なるため、回避策が必要です。詳しくは「Macintosh でのドラッグ アンド ドロップ イベント」を参照してください。


Code Recipe Silverlight デベロッパー センター

ページのトップへ