ドラッグ&ドロップは最も代表的なマウス操作の一つです。
[jin_icon_check color=”#e9546b” size=”14px”] ドラッグ(drag)とは”引きずる”、”引きずって行く”という意味です
[jin_icon_check color=”#e9546b” size=”14px”] ドロップ(drop)とは”落とす”という意味です。
この記事では、「ListBox にドラッグ&ドロップする方法」と 「ListBox から他のコントロールへドラッグ&ドロップする方法」を紹介しています。是非参考にしてみてください。
ListBoxの使い方を復習したい方はこちらからどうぞ。
ListBoxにドラッグ&ドロップしてファイル名を表示する
デザイナ(XAML)
画面に ListBox コントロールを配置します。
ListBox に対してドラッグ&ドロップが使用できるように、必ず AllowDrop プロパティの設定を true にします。初期値は false になっており、ドラッグ&ドロップの操作はできません。
[jin_icon_arrowcircle color=”#e9546b” size=”14px”] AllowDrop プロパティ
ドラッグ&ドロップ操作の対象として使用できるかどうかを示す値を取得または設定します。
ドロップ&ドロップされた時にイベントが発生して処理が実行されるように DragOver イベントと Drop イベントを設定します。
[jin_icon_arrowcircle color=”#e9546b” size=”14px”] DragOver イベント
オブジェクトがドロップ ターゲットとして機能する要素の境界内にドラッグされたときに継続的に発生します。
[jin_icon_arrowcircle color=”#e9546b” size=”14px”] Drop イベント
ドロップ先として機能するコントロールの境界内でオブジェクトがドロップされた時点で発生します。
XAML は次のようになります。
<Window
x:Class="ListBoxSample.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:local="clr-namespace:ListBoxSample"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="400"
Height="250"
mc:Ignorable="d">
<Grid>
<ListBox
Name="lstSample"
Margin="10"
AllowDrop="True"
DragOver="lstSample_DragOver"
Drop="lstSample_Drop" />
</Grid>
</Window>
ソースコード(C#)
DropOver イベントにはListBox の上にドラッグした時に、データ形式がファイルの時だけデータを受け取り、適切なカーソルの形状に変わるように処理を追加します。
マウスカーソルの形状は、DragDropEffects 列挙体の値によって変化します。
DragDrop Effects |
値 | マウス 形状 |
説明 |
All | -2147483645 | 「Copy」「Move」「Scroll」の3つを組み合わせたもの。ドロップ先で、データがコピーされたり、移動されたり、スクロールが発生したりする状態。 | |
None | 0 | いかなるデータもドロップ先が受け付けようとしない状態。 | |
Copy | 1 | データがドロップ先にコピーされようとしている状態。 | |
Move | 2 | データがドロップ先に移動されようとしている状態。 | |
Link | 4 | データのリンクがドロップ先に作成されようとしている状態。 | |
Scroll | -2147483645 | データによってドロップ先でスクロールが開始されようとしている状態、あるいは現在スクロール中である状態。 |
Drop イベントにはドラッグ&ドロップされたファイル名を GetData メソッドで取得してます。このメソッドは複数のドロップされたファイル名を配列に格納して返します。
for 文を使って配列の要素を ListBox に追加して表示します。
ソースコードは次のようになります。
using System.IO;
using System.Windows;
using System.Windows.Controls;
namespace ListBoxSample
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void lstSample_DragOver(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effects = DragDropEffects.All;
}
else
{
e.Effects = DragDropEffects.None;
}
e.Handled = true;
}
private void lstSample_Drop(object sender, DragEventArgs e)
{
var listBox = sender as ListBox;
if (listBox == null) return;
var dropFiles = e.Data.GetData(DataFormats.FileDrop) as string[];
if (dropFiles == null) return;
for (int i = 0; i < dropFiles.Length; i++)
{
//ドロップされたものがファイルかどうかを確認
if (File.Exists(dropFiles[i]))
{
listBox.Items.Add(dropFiles[i]);
}
}
}
}
}
プログラムの実行
上記のコードでプログラムを実行してみます。
Cドライブにある3つのテキストファイルを ListBox にドラッグ&ドロップします。
このように3つのテキストファイルのファイル名を取得して表示する事ができました。
ListBoxから別Controlへドラッグ&ドロップで移動する
デザイナ(XAML)
画面に ListBox コントロールと Label コントロールを配置します。
ListBox から Label へドラッグ&ドロップができるように AllowDrop プロパティの設定を true にします。ドロップ先の Label には DragOver イベントと Drop イベントを設定します。
ドラッグ元の ListBox には PreviewMouseLeftButtonDown イベントを設定します。ここでは予め、ListBox の ListBoxItem で項目を追加しておきます。
[jin_icon_arrowcircle color=”#e9546b” size=”14px”] PreviewMouseLeftButtonDown メソッド
この要素の上にマウス ポインターがある状態でマウスの左ボタンが押されたときに発生します。
XAML は次のようになります。
<Window
x:Class="ListBoxSample.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:local="clr-namespace:ListBoxSample"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="400"
Height="250"
mc:Ignorable="d">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListBox
Name="lstSample"
Margin="10"
PreviewMouseLeftButtonDown="lstSample_PreviewMouseLeftButtonDown">
<ListBoxItem>Item 1</ListBoxItem>
<ListBoxItem>Item 2</ListBoxItem>
<ListBoxItem>Item 3</ListBoxItem>
<ListBoxItem>Item 4</ListBoxItem>
<ListBoxItem>Item 5</ListBoxItem>
<ListBoxItem>Item 6</ListBoxItem>
<ListBoxItem>Item 7</ListBoxItem>
<ListBoxItem>Item 8</ListBoxItem>
<ListBoxItem>Item 9</ListBoxItem>
<ListBoxItem>Item 10</ListBoxItem>
</ListBox>
<StackPanel
Grid.Column="1"
Margin="10"
Orientation="Vertical">
<Label
Height="30"
Margin="0,0,0,5"
AllowDrop="True"
BorderBrush="LightGray"
BorderThickness="1"
DragOver="Label_DragOver"
Drop="Label_Drop" />
<Label
Height="30"
Margin="0,0,0,5"
AllowDrop="True"
BorderBrush="LightGray"
BorderThickness="1"
DragOver="Label_DragOver"
Drop="Label_Drop" />
</StackPanel>
</Grid>
</Window>
ソースコード(C#)
ListBox から別のコントロール(Label)へドラッグ&ドロップできるように、ListBox の PreviewMouseLeftButtonDown イベントにドラッグ操作を行う DoDragDrop メソッドを追加します。
[jin_icon_arrowcircle color=”#e9546b” size=”14px”] DoDragDrop メソッド
ドラッグ アンド ドロップ操作を開始します。
PreViewMouseLeftButtonDown イベントは ListBox のスクロールバーでスクロールした場合もイベントが発生します。そのため、リストボックスの項目を選択した状態でスクロールバーでスクロールするとドラッグ操作が開始されてしまい、スクロールができないという不具合が発生します。
この不具合を回避する為に、リストボックスとスクロールバーの境界となる X座標を算出します。リストボックスのスクロールバーに位置する部分でマウスの左ボタンがクリックされていたら、 DoDragDrop メソッドが実行されないようにします。
ソースコードは次のようになります。
using System.Windows;
using System.Threading.Tasks;
using System.Windows.Controls;
namespace ListBoxSample
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private async void lstSample_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
//項目が選択されるまで待機
await Task.Delay(10);
var listBox = sender as ListBox;
//リストボックスがnullなら戻す
if (listBox == null) return;
//項目が選択されて無いなら戻す
if (listBox.SelectedItem == null) return;
//ListBoxのスクロールバーなら戻す
var margin = listBox.Margin;
var size = listBox.RenderSize;
var scrollbarX = size.Width + margin.Left - 25;
if (scrollbarX < e.GetPosition(null).X)
{
return;
}
//ドラッグ&ドロップを開始
DragDrop.DoDragDrop(listBox, listBox.SelectedItem, DragDropEffects.Copy);
}
private void Label_Drop(object sender, DragEventArgs e)
{
var label = sender as Label;
if (label == null) return;
var item = (ListBoxItem)e.Data.GetData(typeof(ListBoxItem));
if (item == null) return;
label.Content = item.Content;
}
private void Label_DragOver(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(ListBoxItem)))
{
e.Effects = DragDropEffects.Copy;
}
else
{
e.Effects = DragDropEffects.None;
}
e.Handled = true;
}
}
}
プログラムの実行
上記のコードでプログラムを実行してみます。
リストボックスの項目をラベルにドラッグ&ドロップします。
このように選択した項目をラベルに表示する事ができました。
以上、最後まで読んで頂きありがとうございました。