如何在没有NSTreeController的情况下在NSOutlineView中选择项目?

时间:2009-07-08 08:18:33

标签: cocoa select nsoutlineview

我正在使用NSOutlineView 而没有 NSTreeController并且已经实现了我自己的数据源。选择项目的最佳方式是什么? NSOutlineView支持expandItem:collapseItem:。我错过了一个方便的方法,如`selectItem:。我怎么能以编程方式进行呢?

谢谢。

6 个答案:

答案 0 :(得分:21)

以下是我最终的结局。建议和更正总是受欢迎的。

@implementation NSOutlineView (Additions)

- (void)expandParentsOfItem:(id)item {
    while (item != nil) {
        id parent = [self parentForItem: item];
        if (![self isExpandable: parent])
            break;
        if (![self isItemExpanded: parent])
            [self expandItem: parent];
        item = parent;
    }
}

- (void)selectItem:(id)item {
    NSInteger itemIndex = [self rowForItem:item];
    if (itemIndex < 0) {
        [self expandParentsOfItem: item];
        itemIndex = [self rowForItem:item];
        if (itemIndex < 0)
            return;
    }

    [self selectRowIndexes: [NSIndexSet indexSetWithIndex: itemIndex] byExtendingSelection: NO];
}
@end

答案 1 :(得分:19)

当你找不到东西时,请记得查看超类。在这种情况下,您需要的方法之一来自NSTableView,它是NSOutlineView的直接超类。

解决方案是get the row index for the item using rowForItem:,如果它不是-1(项目不可见/未找到),create an index set with it with [NSIndexSet indexSetWithIndex:]并将该索引集传递给the selectRowIndexes:byExtendingSelection: method

答案 2 :(得分:1)

不,没有selectItem:方法,但有rowForItem:方法。如果您将此与Peter关于使用上述selectRowIndexes:byExtendingSelection:的建议相结合,您应该拥有所需的所有信息。

如果您真的想要一种方法来选择一个项目,我建议为了一致性而调用setSelectedItem:,您可以在NSOutlineView

的类别中写下这样的内容
- (void)setSelectedItem:(id)item {
    NSInteger itemIndex = [self rowForItem:item];
    if (itemIndex < 0) {
        // You need to decide what happens if the item doesn't exist
        return;
    }

    [self selectRowIndexes:[NSIndexSet indexSetWithIndex:itemIndex] byExtendingSelection:NO];
}

我不知道这段代码是否真的有效;我只是简单地说明了这个概念。

答案 3 :(得分:0)

以下是我用于以编程方式选择PXSourceList中的项目的代码段。

sourceList是一个常规的PXSouceList对象,我想选择第一组大纲中的第二个项目。

    NSInteger itemRow = [sourceList rowForItem:[[(SourceListItem *)[sourceListItems objectAtIndex:0] children] objectAtIndex:1]];
    [sourceList selectRowIndexes:[NSIndexSet indexSetWithIndex:itemRow] byExtendingSelection:YES];

如果您还不知道,如果您正在寻找iTunes /邮件样式大纲,PXSourceList是NSOutlineView的绝佳替代品。在这里拿起来: PxSourceList

答案 4 :(得分:0)

这是一个古老的问题,但情况仍然相同。由于需要快速版本,这是我的看法。我找不到公认​​的答案对我有用,因为我认为您应该直接与数据源类进行交互,而不是扩展NSOutlineView。烦人的是,除非扩展行,否则大纲将找不到行,这就是为什么使用dataSource更简单的原因。以我为例,我发现您必须以相反的顺序扩展项目的父项,以便您从顶层开始,然后逐步尝试您要扩展的实际项目。我觉得那应该是内置的,但是除非我错过了一些东西,否则不是。

在此示例中,FileItem是我的数据源收集项类。它包含一个属性“父”,如果它是显示的层次结构的一部分,则该属性必须有效。

func selectItem(_ item: FileItem, byExtendingSelection: Bool = false) {
    guard let outlineView = outlineView else { return }

    var itemIndex: Int = outlineView.row(forItem: item)

    if itemIndex < 0 {
        var parent: FileItem? = item

        var parents = [FileItem?]()
        while parent != nil {
            parents.append(parent)
            parent = parent?.parent
        }

        let reversedTree = parents.compactMap({$0}).reversed()

        for level in reversedTree {
            outlineView.expandItem(level, expandChildren: false)
        }

        itemIndex = outlineView.row(forItem: item)
        if itemIndex < 0 {
            print("Didn't find", item)
            return
        }
    }

    print("Expanding row", itemIndex)

    outlineView.selectRowIndexes(IndexSet(integer: itemIndex), byExtendingSelection: byExtendingSelection)
    outlineView.scrollRowToVisible(itemIndex)
}

答案 5 :(得分:0)

(这仍然是Google的头等大事)

迅速4.2:

您需要确保先扩展父级:

if let parent = outlineView.parent(myItem){
        mapOutlineView.expandItem(parent)
}


let rowIndex = outlineView.row(forItem: myItem)
        guard rowIndex != -1 else {return}
        outlineView.selectRowIndexes(IndexSet(integer: rowIndex), byExtendingSelection: false)