XAMLで始めるWPF入門:ドラッグ&ドロップでファイルを渡す。

コンピュータ

ドラッグ&ドロップでファイルの一覧を受け取るヘルパーメソッドを作って見ました。

今回はヘルパーメソッドを使うサンプルプログラムになります。
はじめXAMLを使わないコードを想定していましたが、コードビハインドで使うことも出来そうなのでXAML有りのサンプルプログラムになります。

ドラッグ&ドロップされたファイルの一覧は以下の流れでTextBlockのTextに反映されます。

TextBlockへD&D → コードビハインドでファイルの一覧をTextBlockのTagに反映 → Tagの購読処理でTextBlock.Textに反映

というような流れになっています。

ソースコード

ファイル名:dd01.csproj


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net8.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

</Project>

ファイル名:MainWindow.xaml.cs


using System.Collections.ObjectModel;
using System.Windows;

using NxLib.Helper;

namespace dd01;

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Wiring.AcceptFiles(DdArea, files =>
        {
            if (DdArea.Tag is not ObservableCollection<string>) return;

            ObservableCollection<string> fs = (ObservableCollection<string>)DdArea.Tag;
            fs.Clear();
            foreach(var s in files)
            {
                fs.Add(s);
            }
        });

        DataContext = new MainViewModel();
    }
}

ファイル名:Helpers\Wiring.cs


using System.Windows;

namespace NxLib.Helper;
public static class Wiring
{
    // D&D: 指定拡張子だけ受け付ける(exts 省略可)
    public static void AcceptFiles(FrameworkElement el, Action<string[]> onFiles, params string[] exts)
    {
        el.AllowDrop = true;
        el.Drop += (_, e) =>
        {
            if (!e.Data.GetDataPresent(DataFormats.FileDrop)) return;

            var files = (string[])e.Data.GetData(DataFormats.FileDrop)!;

            if (exts is { Length: > 0 })
                files = files
                    .Where(f => exts.Any(x => f.EndsWith(x, StringComparison.OrdinalIgnoreCase)))
                    .ToArray();

            if (files.Length > 0)
                onFiles(files);
        };
    }
}

ファイル名:ViewModels\MainViewModel.cs


using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;


namespace dd01;

public class MainViewModel : INotifyPropertyChanged
{
    public ObservableCollection<string> Files { get; private set; } = [];
    private string _message = "こちらにドラッグ&ドロップしてください。";
    public string Message
    {
        get => _message;
        set
        {
            if (_message != value)
            {
                _message = value;
                OnPropertyChanged();
            }
        }
    }
    public MainViewModel()
    {
        Files.CollectionChanged += (sender, e) =>
        {
            string msg = "";
            foreach(var s in Files)
            {
                msg += s + "\n";
            };
            Message = msg;
        };
    }

    public event PropertyChangedEventHandler? PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

ファイル名:MainWindow.xaml

<Window x:Class="dd01.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:dd01"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TextBlock
            x:Name="DdArea"
            Text="{Binding Message}"
            Tag="{Binding Files}"
            FontSize="24"
            TextAlignment="Center"
            TextWrapping="Wrap"
            HorizontalAlignment="Center"
            VerticalAlignment="Center" />
    </Grid>
</Window>

実行イメージ

・起動時
image

・ファイルをドラッグ&ドロップ
image
ファイルの一覧が表示される。

コメント