我如何在 MacOS 上使用数据对象(拖放文件)
How I can use a DataObject on MacOS (Drag and Drop files)
DataObject 是 System.Windows 的一部分,在 Xamarin.Mac 中不可用。那么我该如何解决。我想用外部文件创建拖放功能。在 Windows 上,我可以使用 DataObject 来做到这一点。
我已经搜索了替代品,用 NSUrl 尝试过但没有成功。
拖入您的应用:
所有基于 NSView 的 类 都有一个 RegisterForDraggedTypes
方法,你可以传递你想要接受的东西(在你的情况下 UTType.FileURL
当你将一些东西传递到应用程序时,大概来自 Finder 的文件)。
所以在这种情况下,我有一个 NSTableView
接受文件,将它们添加到 table 并触发一个通知,导致 NSTask
处理它们(它是一个 FFMPEG基于任务)。
tableView.RegisterForDraggedTypes(new string[] { UTType.FileURL };
从那里开始取决于您要拖入的 NSView 类型,但是例如对于 NSTableView
,您为其数据委托分配一个 NSTableViewDataSource
子类,您已覆盖 ValidateDrop
和 AcceptDrop
.
在 NSTableViewDataSource.ValidateDrop
中,您确认投放是否包含您将接受的文件。在这种情况下,只要它是我接受的任何类型的文件:
public override NSDragOperation ValidateDrop(NSTableView tableView, NSDraggingInfo info, nint row, NSTableViewDropOperation dropOperation)
{
var operation = NSDragOperation.Copy;
using (var pasteBoard = info.DraggingPasteboard)
{
foreach (var item in pasteBoard.PasteboardItems)
{
if (!item.Types.Contains(UTType.FileURL))
{
operation = NSDragOperation.None;
}
item.Dispose();
}
}
return operation;
}
在 NSTableViewDataSource.AcceptDrop
中,您实际处理了 drop 中的文件。
public override bool AcceptDrop(NSTableView tableView, NSDraggingInfo info, nint row, NSTableViewDropOperation dropOperation)
{
using (var pasteBoard = info.DraggingPasteboard)
{
if (pasteBoard.PasteboardItems.Length > 0)
{
var range = new NSRange(-1, 0);
foreach (var item in pasteBoard.PasteboardItems)
{
if (item.Types.Contains(UTType.FileURL))
{
var finderNode = item.GetStringForType(UTType.FileURL);
// you have a file from macOS' finder, do something with it, assumable in a table view you would add a record/row....
var url = NSUrl.FromString(finderNode);
// url has the file extension, filename, full path, etc...
Post a notification / Add a task to GCD / etc...
}
item.Dispose();
}
return true;
}
}
return false;
}
拖出您的应用程序:
假设您有一个 NSView
子类,您希望将 "file" 拖出和拖入 Finder 或任何接受文件拖放的应用程序。实现接口; INSDraggingSource
和 INSPasteboardItemDataProvider
在你的 NSView
子类上。
在 MouseDown
事件中,开始拖动 UTType.FileURL
类型:
public override void MouseDown(NSEvent theEvent)
{
var pasteboardItem = new NSPasteboardItem();
pasteboardItem.SetDataProviderForTypes(this, new string[1] { UTType.FileURL });
var draggingItem = new NSDraggingItem(pasteboardItem);
var fileDragIcon = new NSImage("theDraggingIcon.png");
draggingItem.SetDraggingFrame(new CoreGraphics.CGRect(0,0,40,40), fileDragIcon);
BeginDraggingSession(new NSDraggingItem[1] { draggingItem }, theEvent, this);
}
在 ProvideDataForType
中将文件 url 放到粘贴板上:
public void ProvideDataForType(NSPasteboard pasteboard, NSPasteboardItem item, string type)
{
if (type == UTType.FileURL )
{
var url = new NSUrl("/Users/Sushi/Desktop/Whosebug.png", false);
url.WriteToPasteboard(pasteboard);
}
}
注意:这只是传输文件的一种方式,还有其他三种文件拖传输,你也可以提供一个url数组,承诺稍后自己创建文件并实际插入将文件的数据放入粘贴板。
DataObject 是 System.Windows 的一部分,在 Xamarin.Mac 中不可用。那么我该如何解决。我想用外部文件创建拖放功能。在 Windows 上,我可以使用 DataObject 来做到这一点。
我已经搜索了替代品,用 NSUrl 尝试过但没有成功。
拖入您的应用:
所有基于 NSView 的 类 都有一个 RegisterForDraggedTypes
方法,你可以传递你想要接受的东西(在你的情况下 UTType.FileURL
当你将一些东西传递到应用程序时,大概来自 Finder 的文件)。
所以在这种情况下,我有一个 NSTableView
接受文件,将它们添加到 table 并触发一个通知,导致 NSTask
处理它们(它是一个 FFMPEG基于任务)。
tableView.RegisterForDraggedTypes(new string[] { UTType.FileURL };
从那里开始取决于您要拖入的 NSView 类型,但是例如对于 NSTableView
,您为其数据委托分配一个 NSTableViewDataSource
子类,您已覆盖 ValidateDrop
和 AcceptDrop
.
在 NSTableViewDataSource.ValidateDrop
中,您确认投放是否包含您将接受的文件。在这种情况下,只要它是我接受的任何类型的文件:
public override NSDragOperation ValidateDrop(NSTableView tableView, NSDraggingInfo info, nint row, NSTableViewDropOperation dropOperation)
{
var operation = NSDragOperation.Copy;
using (var pasteBoard = info.DraggingPasteboard)
{
foreach (var item in pasteBoard.PasteboardItems)
{
if (!item.Types.Contains(UTType.FileURL))
{
operation = NSDragOperation.None;
}
item.Dispose();
}
}
return operation;
}
在 NSTableViewDataSource.AcceptDrop
中,您实际处理了 drop 中的文件。
public override bool AcceptDrop(NSTableView tableView, NSDraggingInfo info, nint row, NSTableViewDropOperation dropOperation)
{
using (var pasteBoard = info.DraggingPasteboard)
{
if (pasteBoard.PasteboardItems.Length > 0)
{
var range = new NSRange(-1, 0);
foreach (var item in pasteBoard.PasteboardItems)
{
if (item.Types.Contains(UTType.FileURL))
{
var finderNode = item.GetStringForType(UTType.FileURL);
// you have a file from macOS' finder, do something with it, assumable in a table view you would add a record/row....
var url = NSUrl.FromString(finderNode);
// url has the file extension, filename, full path, etc...
Post a notification / Add a task to GCD / etc...
}
item.Dispose();
}
return true;
}
}
return false;
}
拖出您的应用程序:
假设您有一个 NSView
子类,您希望将 "file" 拖出和拖入 Finder 或任何接受文件拖放的应用程序。实现接口; INSDraggingSource
和 INSPasteboardItemDataProvider
在你的 NSView
子类上。
在 MouseDown
事件中,开始拖动 UTType.FileURL
类型:
public override void MouseDown(NSEvent theEvent)
{
var pasteboardItem = new NSPasteboardItem();
pasteboardItem.SetDataProviderForTypes(this, new string[1] { UTType.FileURL });
var draggingItem = new NSDraggingItem(pasteboardItem);
var fileDragIcon = new NSImage("theDraggingIcon.png");
draggingItem.SetDraggingFrame(new CoreGraphics.CGRect(0,0,40,40), fileDragIcon);
BeginDraggingSession(new NSDraggingItem[1] { draggingItem }, theEvent, this);
}
在 ProvideDataForType
中将文件 url 放到粘贴板上:
public void ProvideDataForType(NSPasteboard pasteboard, NSPasteboardItem item, string type)
{
if (type == UTType.FileURL )
{
var url = new NSUrl("/Users/Sushi/Desktop/Whosebug.png", false);
url.WriteToPasteboard(pasteboard);
}
}
注意:这只是传输文件的一种方式,还有其他三种文件拖传输,你也可以提供一个url数组,承诺稍后自己创建文件并实际插入将文件的数据放入粘贴板。