LoginSignup
4
0

More than 5 years have passed since last update.

Xamarin.MacのウインドウでDrag&Dropを受け入れる

Posted at

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の作法的なものがわかります?

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0