Avaloniaという、C#でマルチプラットフォームなGUIが作れるフレームワークを試していました
AvaloniaはWPFの精神的後継者を自称するなど全体的にWPFっぽく(WPF触ったことないけど)、簡単なことであれば「WPF + やりたいこと」で検索してそのとおりにやればできることが多いです
が、ドラッグアンドドロップはそうでもなかった上情報がかなり少なさそうなので書きます
完成品
起動すると文字入りのウィンドウが開き、ウィンドウにファイルやフォルダを投げると絶対パスを、テキストを選択して投げるとテキストを文字で表示します
MVVMテンプレートから作成しました
画像はFドライブのProgram Filesフォルダを投げた場合です
GitHubに上げてます
Windows11でしか動作確認していません
参考
Mamma Mia Dev様の解説動画
Redditで同じようなことをしていた質問
DragEventArgsの公式リファレンス
https://reference.avaloniaui.net/api/Avalonia.Input/DragEventArgs/
IDataObjectの公式リファレンス
https://reference.avaloniaui.net/api/Avalonia.Input/IDataObject/
やる
まず、Avaloniaでドラッグアンドドロップを実装する方法は公式ドキュメントには全然情報がなく、上記参考をもとに適当に書いたものなので間違いあったらごめんなさい
<Window 省略~
DragDrop.AllowDrop="True">
ドラッグアンドドロップを受け入れたいコントロールのDragDrop.AllowDropプロパティをTrueにします
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
AddHandler(DragDrop.DropEvent, DropFile); //登録を忘れない 多分xaml側では不可能
}
private void DropFile(object? sender, DragEventArgs e)
{
var dropData = e.Data;
//ここに受け取った情報を使う処理を書く
}
}
コードビハインドでファイルがドロップされたときの処理を書いていきますが、この処理をコンストラクタにてAddHandler(DragDrop.DropEvent, DropFile);
で登録しなければいけないようです
DragEventArgsの使い勝手がWPFのそれと若干違う?
あとはDragEventArgsから受け取ったやつ使って処理書けばOK!なんですが
このDragEventArgs型はWPFのそれとは別物で、受け取れるDataも別物になります
私はここで苦戦しました
このDataはAvalonia.Input.IDataObject
型で、例えば受け取ったもののパスが欲しいなとなったときに、前述の公式リファレンスを見るとGetFileNames()
といういかにもなメソッドが使えるようなのですが実際には使えません(なんでだ?)
手探りでやった結果このような形に行きつきました
CenterTextという名前のstring型プロパティにパスをセットするコードの一部です
if(data.GetText() != null)
{
//もし受け取ったのがテキストであればそれにセット
CenterText = data.GetText();
return;
}
else
{
if(data.GetFiles != null)
{
//複数ファイルをドロップしても全部のパスを読むようにする
List<string> path = new();
foreach (var item in data.GetFiles())
{
path.Add(item.Path.ToString());
}
if(path.Count > 0)
{
CenterText = string.Join("\n", path);
}
}
}
GetFiles
というメソッドを使いファイルのコレクションを取得しています
ちなみにGetFilesメソッドですがこっちは使えるのになぜかリファレンスに乗っていません
まとめ
WPFは枯れた技術だからか情報が多くてすごい
リファレンスうんぬんは私が間違っている可能性もあるので、教えていただければ修正します
参考になれば幸いです