从 NSOutlineView 中拖放

Posted

技术标签:

【中文标题】从 NSOutlineView 中拖放【英文标题】:Drag and drop from within a NSOutlineView 【发布时间】:2012-08-28 19:33:00 【问题描述】:

我正在尝试弄清楚如何实现从 NSOutlineView 到自身的拖放。

例如,我希望用户能够在 NSOutlineView 中重新排序和嵌套和重新嵌套项目,但我不需要能够从任何其他来源(如文件或其他视图)拖动项目)。

我能找到的所有示例都涉及将项目拖动到 NSOutlineView 中,而不仅仅是在其内部,而且看起来过于复杂。我认为这是可能的。

有人可以指出一些处理这种情况的文档吗?也许我只是错过了显而易见的事情。

【问题讨论】:

你的意思是拖一个视图然后放到它本身? 查看code example。它对一些高级 NSTableView/NSOutlineView 操作有一些提示。 仅供参考,这里有另一个链接解释得很好 --> cocoabuilder.com/archive/cocoa/… 【参考方案1】:

我发现这方面的文档有些不清楚,除其他外,Lion 中添加了新的方法。

假设您需要 10.7 或更高版本,那么这可能是您实现的框架:

在您的数据源/委托类中,实现:

// A method to register the view for dragged items from itself. 
// Call it during initialization
-(void) enableDragNDrop

    [self.outlineView registerForDraggedTypes: [NSArray arrayWithObject: @"DragID"]];



- (id <NSPasteboardWriting>)outlineView:(NSOutlineView *)outlineView pasteboardWriterForItem:(id)item 

    // No dragging if <some condition isn't met>

    if ( dontDrag )  
        return nil;
    

    // With all the blocking conditions out of the way,
    // return a pasteboard writer.

    // Implement a uniqueStringRepresentation method (or similar)
    // in the classes that you use for your items.
    // If you have other ways to get a unique string representation
    // of your item, you can just use that.
    NSString *stringRep = [item uniqueStringRepresentation];

    NSPasteboardItem *pboardItem = [[NSPasteboardItem alloc] init];

    [pboardItem setString:stringRep forType: @"DragID"];

    return pboardItem;



- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id < NSDraggingInfo >)info proposedItem:(id)item proposedChildIndex:(NSInteger)index

    BOOL dragOK = // Figure out if your dragged item(s) can be dropped
                  // on the proposed item at the index given

    if ( dragOK ) 
        return NSDragOperationMove;
    
    else 
        return NSDragOperationNone;
    



- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id < NSDraggingInfo >)info item:(id)item childIndex:(NSInteger)index
           
    // Move the dragged item(s) to their new position in the data model
    // and reload the view or move the rows in the view.
    // This is of course quite dependent on your implementation        

最后一种方法需要填写大量代码,关于动画运动,samir 评论中提到的 Apple 的 complex table view demo code 非常有用,虽然有点难以解读。

【讨论】:

是的,对于措辞不当的问题,我深夜发帖时会发生这种情况。您的解决方案看起来像我需要的。我今晚一回家就试试看。 谢谢,这工作得很好,除了我必须让粘贴板接受 NSStrings 而不是用户类型,无论如何这更容易。谢谢! 我得到“选择器'uniqueStringRepresentation'没有已知的实例方法”。那是什么? @bababa 它只是用作某些方法的占位符,为项目生成唯一的字符串表示。您必须根据您的项目为自己编写它 - 只有您知道它们是如何定义的以及如何对它们进行独特的表示。 @bababa 在这里显示的代码中是的,因为它需要作为NSPasteboardItemsetString:forType: 方法的参数。查看documentation 了解其他选项。【参考方案2】:

我创建了一个small sample project,其中有一个NSOutlineView,您可以在其中添加和删除项目。

今天我根据@Monolo 的回答 (See changes) 实现了拖放支持。

【讨论】:

这绝对是完美的。谢谢。

以上是关于从 NSOutlineView 中拖放的主要内容,如果未能解决你的问题,请参考以下文章

NSTableView 和 NSOutlineView 拖放

如何使用 react-dnd 从材质 UI 中拖放 TableHeaderColumn?

关于 NSOutlineView 和 WriteItem |拖放问题

Qt - 在QGraphicScene中拖放时如何从项目中获取文本?

SwiftUI:如何从 macOS 上的联系人中拖放联系人

需要在icarousel中拖放视图