macos 如何使用 Cocoa Bindings 实现基于视图的源列表 (NSOutlineView) 的示例?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8090224/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 08:35:59  来源:igfitidea点击:

Example of how to implement a view-based source list (NSOutlineView) using Cocoa Bindings?

macoscocoacocoa-bindingsnsoutlineview

提问by John Wells

Has anybody found a clear, concise example or guide on how to implement a source list using the view-based NSOutlineView introduced in Lion? I've looked at Apple's example project, but without any sense of direction or explanation, I'm finding it difficult to grasp the concept of exactly how they work.

有没有人找到关于如何使用 Lion 中引入的基于视图的 NSOutlineView 来实现源列表的清晰、简洁的示例或指南?我看过 Apple 的示例项目,但没有任何方向感或解释,我发现很难掌握它们究竟如何工作的概念。

I know how to use the excellent PXSourceList as a fallback, but would really like to start using view-based source lists instead if at all possible.

我知道如何使用优秀的 PXSourceList 作为后备,但如果可能的话,我真的很想开始使用基于视图的源列表。

回答by ipmcc

You tagged this with the cocoa-bindings tag, so I assume you mean "with bindings." I whipped up a quick example. Start from a new non-document-based Cocoa Application template in Xcode. Call it whatever you like. First I added some code to make some fake data to bind to. Here's what my AppDelegate header looks like:

你用 cocoa-bindings 标签标记了它,所以我假设你的意思是“有绑定”。我举了一个简单的例子。从 Xcode 中一个新的非基于文档的 Cocoa 应用程序模板开始。你喜欢怎么称呼它。首先,我添加了一些代码来制作一些要绑定的假数据。这是我的 AppDelegate 标头的样子:

#import <Cocoa/Cocoa.h>

@interface SOAppDelegate : NSObject <NSApplicationDelegate>

@property (assign) IBOutlet NSWindow *window;

@property (retain) id dataModel;

@end

And here's what my AppDelegate implementation looks like:

这是我的 AppDelegate 实现的样子:

#import "SOAppDelegate.h"

@implementation SOAppDelegate

@synthesize window = _window;
@synthesize dataModel = _dataModel;

- (void)dealloc
{
    [_dataModel release];
    [super dealloc];
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application

    // Make some fake data for our source list.
    NSMutableDictionary* item1 = [NSMutableDictionary dictionaryWithObjectsAndKeys: @"Item 1", @"itemName", [NSMutableArray array], @"children", nil];
    NSMutableDictionary* item2 = [NSMutableDictionary dictionaryWithObjectsAndKeys: @"Item 2", @"itemName", [NSMutableArray array], @"children", nil];
    NSMutableDictionary* item2_1 = [NSMutableDictionary dictionaryWithObjectsAndKeys: @"Item 2.1", @"itemName", [NSMutableArray array], @"children", nil];
    NSMutableDictionary* item2_2 = [NSMutableDictionary dictionaryWithObjectsAndKeys: @"Item 2.2", @"itemName", [NSMutableArray array], @"children", nil];
    NSMutableDictionary* item2_2_1 = [NSMutableDictionary dictionaryWithObjectsAndKeys: @"Item 2.2.1", @"itemName", [NSMutableArray array], @"children", nil];
    NSMutableDictionary* item2_2_2 = [NSMutableDictionary dictionaryWithObjectsAndKeys: @"Item 2.2.2", @"itemName", [NSMutableArray array], @"children", nil];
    NSMutableDictionary* item3 = [NSMutableDictionary dictionaryWithObjectsAndKeys: @"Item 3", @"itemName", [NSMutableArray array], @"children", nil];

    [[item2_2 objectForKey: @"children"] addObject: item2_2_1];
    [[item2_2 objectForKey: @"children"] addObject: item2_2_2];

    [[item2 objectForKey: @"children"] addObject: item2_1];
    [[item2 objectForKey: @"children"] addObject: item2_2];

    NSMutableArray* dataModel = [NSMutableArray array];

    [dataModel addObject: item1];
    [dataModel addObject: item2];
    [dataModel addObject: item3];

    self.dataModel = dataModel;
}

@end

There's no particular significance to the fake data structure I created, I just wanted to show something with a couple of sub-levels, etc. The only thing that matters is that the key paths you specify in the bindings in Interface Builder line up with the keys in your data (fake data in this case.)

我创建的假数据结构没有特别的意义,我只是想展示一些带有几个子级别的东西,等等。唯一重要的是你在 Interface Builder 的绑定中指定的关键路径与数据中的键(在这种情况下是假数据。)

Then select the MainMenu.xibfile. In the IB editor, do the following steps:

然后选择MainMenu.xib文件。在 IB 编辑器中,执行以下步骤:

  1. Use the Object Library (Ctrl-Cmd-Opt-3) to add an NSTreeController to your .xib.
  2. Select the NSTreeController, and using the Attributes Inspector (Cmd-Opt-4) set Key Paths > Childrento children(for this example; For your data, this should be whatever returns the array of child objects.)
  3. With the NSTreeController still selected, use the Bindings Inspector (Cmd-Opt-7) to bind the Content Arrayto the AppDelegate, with a Model Key Path of dataModel
  4. Next use the Object Library (Ctrl-Cmd-Opt-3) to add an NSOutlineView to your .xib.
  5. Arrange it to your satisfaction inside the window (typically the entire height of the window, flush against the left-hand side)
  6. Select the NSOutlineView (note that the first time you click on it, you have likely selected the NSScrollView that contains it. Click on it a second time and you'll have drilled-down to the NSOutlineView itself. Note that this is MUCHeasier if you widen the area on the left of the IB editor where all the objects are -- this allows you see the objects as a tree, and navigate and select them that way.)
  7. Using the Attributes Inspector (Cmd-Opt-4) set the NSOutlineView:
    • Content Mode: View Based
    • Columns: 1
    • Highlight: Source List
  8. Using the Bindings Inspector (Cmd-Opt-7) bind "Content" to "Tree Controller", Controller Key: arrangedObjects (This is where the behavior of View-based NSTableView/NSOutlineViews starts to diverge from NSCell-based ones)
  9. In the Object List (mentioned in #6), expand the view hierarchy of the NSOutlineView and select Static Text - Table View Cell.
  10. Using the Bindings Inspector (Cmd-Opt-7) bind Valueto Table Cell View, Model Key Path: objectValue.itemName(I've used itemNamein the fake data, you would want to use whichever key corresponded to the name of your data items)
  1. 使用对象库 (Ctrl-Cmd-Opt-3) 将 NSTreeController 添加到您的.xib.
  2. 选择 NSTreeController,并使用 Attributes Inspector (Cmd-Opt-4) 将Key Paths > Children设置为children(对于此示例;对于您的数据,这应该是返回子对象数组的任何内容。)
  3. 在 NSTreeController 仍然选中的情况下,使用 Bindings Inspector (Cmd-Opt-7) 将Content Array绑定到 AppDelegate,Model Key Path 为dataModel
  4. 接下来使用对象库 (Ctrl-Cmd-Opt-3) 将 NSOutlineView 添加到您的.xib.
  5. 将其安排在您满意的窗口内(通常是窗口的整个高度,与左侧齐平)
  6. 选择NSOutlineView(注意,第一次你点击它,你可能已经选择了包含它的NSScrollView,点击它第二次,你就会有钻,下至NSOutlineView本身。注意,这是MUCH如果容易您可以扩大 IB 编辑器左侧所有对象所在的区域——这允许您将对象视为一棵树,并以这种方式导航和选择它们。)
  7. 使用属性检查器 (Cmd-Opt-4) 设置 NSOutlineView:
    • 内容模式View Based
    • 1
    • 亮点Source List
  8. 使用绑定检查器(Cmd-Opt-7)将“内容”绑定到“树控制器”,控制器键:排列对象(这是基于视图的 NSTableView/NSOutlineViews 的行为开始与基于 NSCell 的行为不同的地方)
  9. 在 Object List(在 #6 中提到)中,展开 NSOutlineView 的视图层次结构并选择Static Text - Table View Cell
  10. 使用绑定检查器(Cmd-Opt-7)将绑定到Table Cell View模型键路径:(objectValue.itemNameitemName在假数据中使用过,您会想要使用与数据项名称相对应的键)

Save. Run. You should see a source list, and once you've expanded the nodes with children, you might see something like this:

保存。跑。您应该会看到一个源列表,一旦您用子节点展开节点,您可能会看到如下内容:

enter image description here

enter image description here

If you're in the Apple Developer Program, you should be able to access the WWDC 2011 Videos. There's one specifically dedicated to working with View-based NSTableView (and NSOutlineView) and it includes pretty thorough coverage of bindings.

如果您加入了 Apple Developer Program,您应该能够访问WWDC 2011 Videos。有一个专门用于使用基于视图的 NSTableView(和 NSOutlineView),它包括对绑定的非常全面的覆盖。

Hope that helps!

希望有帮助!

回答by Cory

Take a look at this example.

看看这个例子。

SideBarDemo

边栏演示