Xamarin.MacにDrag&Drop
忘備録です。
Window(正確にはView)でDrag&Dropを受け入れる方法です。
と言っても、Objective-Cと同じことするだけなのですが。
なお、アドベントカレンダーで書いた方法でXamarin.FormsのページをViewの上に被せる方法を使った場合でも親ViewでDrag&Dropを捕まえてくれます。
ファイルをDropできるようにする
NSViewのサブクラスを作成する
namespace Views
{
public class MainView : AppKit.NSView
{
public MainView(IntPtr handle) : base(handle)
{
Initialize();
}
[Export("initWithCoder:")]
public MainView(NSCoder coder) : base(coder)
{
Initialize();
}
void Initialize()
{
}
}
}
ソリューションビュー内で 右クリック→追加→新しいファイル として、サブクラスを作り、xibでもstoryboardでも割り付けて使えるようにします。
Dropできる形式を登録する
Initialize
関数内でDropできる形式を登録します。
void Initialize()
{
RegisterForDraggedTypes(new string[] { NSPasteboard.NSFilenamesType });
}
これで、View内でファイルをDropできると認識させておきます。
DragされてきたときにDropで受け入れるかチェックする
string[] GetFilesFromDraggingInfo(NSDraggingInfo info)
{
var pb = info.DraggingPasteboard;
var files = new List<string>();
var t = pb.GetAvailableTypeFromArray(RegisteredDragTypes());
if (t == NSPasteboard.NSFilenamesType)
{
var lists = pb.GetPropertyListForType(NSPasteboard.NSFilenamesType);
if (lists is NSArray)
{
var arr = lists as NSArray;
for (nuint i = 0; i < arr.Count; i++)
{
var item = arr.GetItem<NSString>(i);
var ext = Path.GetExtension(item).ToLower();
if (ext == ".epub")
{
files.Add(item);
}
}
}
}
return files.ToArray();
}
public override NSDragOperation DraggingEntered(NSDraggingInfo sender)
{
var files = GetFilesFromDraggingInfo(sender);
if(files.Length > 0)
{
return NSDragOperation.Copy;
}
return NSDragOperation.Generic;
}
GetFilesFromDraggingInfo
関数で行なっているのは、Dragされてきたものがファイルで拡張子がepubか確認し、そのファイル名のみを配列で抜き出す、ということを行なっています。
DraggingEntered
関数は、DragされてView内に入ってきたときに呼び出される関数で、受け入れるなら受け入れる方法を返答します。
以下の形式を返すようにします。
- NSDragOperation.None
- 何もしない
- NSDragOperation.Copy
- コピーとして受け入れる
- NSDragOperation.Link
- リンクとして受け入れる
- NSDragOperation.Move
- 移動として受け入れる
- NSDragOperation.Generic
- 何もしない(Noneとは意味合いが違う)
返答により、マウスカーソル周りの表示が色々変わります。
Dropを受け入れる
public override bool PerformDragOperation(NSDraggingInfo sender)
{
var files = GetFilesFromDraggingInfo(sender);
foreach (var file in files)
{
Debug.WriteLine($"drop file:{file}");
}
return files.Length > 0;
}
PerformDragOperation
はDropを受け入れるかどうかを最終的に判断する部分です。
マウスボタンを離した瞬間に呼ばれます。
trueを返すと受け入れ、falseを返すと受け入れない、となっており、これによって戻っていくアニメーションなどが表示されます。
Object-Cそのまま
実は、ここ(ドラッグ&ドロップされた複数のファイルのパスを得るカスタムView:Qiita)とほとんど同じです。
見比べればXamarin.Macの作法的なものがわかります?