C#

【WPF】ListBoxでドラッグ&ドロップを使ってみた(C#)

ドラッグ&ドロップは最も代表的なマウス操作の一つです。

ドラッグ(drag)とは”引きずる”、”引きずって行く”という意味です

ドロップ(drop)とは”落とす”という意味です。

この記事では、「ListBox にドラッグ&ドロップする方法」と 「ListBox から他のコントロールへドラッグ&ドロップする方法」を紹介しています。是非参考にしてみてください。

ListBoxの使い方を復習したい方はこちらからどうぞ。

【WPF】ListBox(リストボックス)の使い方と書き方を紹介WPFではListBox(リストボックス)と呼ばれる、データを一覧で表示して項目を選択できるGUIコントロールがあります。この記事ではListBoxの使い方や書き方を知りたい方にはオススメです。ぜひ最後まで読んでみて下さい。...

ListBoxにドラッグ&ドロップしてファイル名を表示する

デザイナ(XAML)

画面に ListBox コントロールを配置します。

ListBox に対してドラッグ&ドロップが使用できるように、必ず AllowDrop プロパティの設定を true にします。初期値は false になっており、ドラッグ&ドロップの操作はできません。

AllowDrop プロパティ
ドラッグ&ドロップ操作の対象として使用できるかどうかを示す値を取得または設定します。

ドロップ&ドロップされた時にイベントが発生して処理が実行されるように DragOver イベントDrop イベントを設定します。

DragOver イベント
オブジェクトがドロップ ターゲットとして機能する要素の境界内にドラッグされたときに継続的に発生します。

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つを組み合わせたもの。ドロップ先で、データがコピーされたり、移動されたり、スクロールが発生したりする状態。
None0いかなるデータもドロップ先が受け付けようとしない状態。
Copy1データがドロップ先にコピーされようとしている状態。
Move2データがドロップ先に移動されようとしている状態。
Link4データのリンクがドロップ先に作成されようとしている状態。
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 で項目を追加しておきます。

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 メソッドを追加します。

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;
        }
    }
}

 

プログラムの実行

上記のコードでプログラムを実行してみます。

リストボックスの項目をラベルにドラッグ&ドロップします。

このように選択した項目をラベルに表示する事ができました。

 

以上、最後まで読んで頂きありがとうございました。

プログラミングを学習したいなら…

プログラミングスキルを身に付けるなら、プログラミングを効率良く学べる
プログラミングスクール」がオススメです。

特にこんな方にオススメ!!
これからエンジニアを目指したい
プログラミングの専門性を高めたい
プログラミングを学んで副業をしたい
エンジニアに転職して年収をアップさせたい

プログラミングを触ったことがない未経験からでも、プログラミングスクールで学習すれば、エンジニアへ就職・転職することも可能です。

あなたの「行動力」と「やる気」で、あなたの人生を大きく変えるチャンスになることでしょう。

プログラミングスクールに興味がある方は是非チェックしてみてください。

> プログラミングを学ぶ <

COMMENT

メールアドレスが公開されることはありません。

CAPTCHA