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