前回はコントロールのTagを使いドラッグ&ドロップされたファイルの一覧を渡していましたが、コードビハインドからViewModelのメソッドを呼び出しても良いとのことですので、変更してみました。
直接呼び出しだと依存度が高そうなので、申し訳程度にインターフェイスを経由するようにしてあります。
ソースコード
ファイル名: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 Microsoft.VisualBasic;
using NxLib.Helper;
namespace dd01;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var vm = new MainViewModel();
DataContext = vm;
Wiring.AcceptFiles(DdArea, files =>
{
(DataContext as IAcceptFiles)?.SetFiles(files);
});
}
}
ファイル名: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\IAcceptFiles.cs
namespace dd01;
public interface IAcceptFiles
{
void SetFiles(IEnumerable<string> files);
}
ファイル名:ViewModels\MainViewModel.cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace dd01;
public class MainViewModel : INotifyPropertyChanged, IAcceptFiles
{
public ObservableCollection<string> Files { get; private set; } = [];
private string _message = "こちらにドラック&ドロップしてください。";
public string Message
{
get => _message;
set
{
if (_message != value)
{
_message = value;
OnPropertyChanged();
}
}
}
public MainViewModel()
{
}
public void SetFiles(IEnumerable<string> files)
{
Files.Clear();
foreach (var s in files) Files.Add(s);
Message = string.Join(Environment.NewLine, Files);
}
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}"
FontSize="24"
TextAlignment="Center"
TextWrapping="Wrap"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</Window>
コメント