13

我正在使用NSOutlineView 并且 NSTreeController已经实现了我自己的数据源。选择项目的最佳方法是什么? NSOutlineView已经支持expandItem:collapseItem:。而且我缺少一个方便的方法,例如`selectItem:。我怎样才能以编程方式做到这一点?

谢谢你。

4

6 回答 6

23

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

解决方案是使用获取项目的行索引rowForItem:,如果它不是 -1(项目不可见/未找到),则使用它创建一个索引集[NSIndexSet indexSetWithIndex:]并将该索引集传递selectRowIndexes:byExtendingSelection:方法

于 2009-07-08T11:18:15.883 回答
22

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

@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
于 2009-08-19T13:11:39.070 回答
2

不,没有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];
}

我不知道这段代码是否真的有效;我只是为了说明这个概念而删掉它。

于 2009-07-08T14:31:30.017 回答
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

于 2011-06-04T19:55:06.340 回答
0

这是一个老问题,但情况还是一样。由于有一个快速版本的要求,这是我的看法。我没有找到适合我的公认答案,因为我认为您应该直接与数据源类进行交互,而不是扩展 NSOutlineView。烦人的是,大纲不会找到行,除非它们被展开,这就是使用数据源更简单的原因。就我而言,我发现您必须以相反的顺序扩展您的项目的父项,以便您从顶层开始并朝着您要扩展的实际项目前进。我觉得应该内置,但除非我错过了什么 - 它不是。

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

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)
}
于 2019-01-11T23:24:18.490 回答
0

(这仍然是谷歌的最高结果)

斯威夫特 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)
于 2020-07-25T12:54:43.530 回答