简体   繁体   English

将NSArrayController绑定到NSPopupButton和NSTextField

[英]Binding a NSArrayController to a NSPopupButton & NSTextField

What I want to accomplish seems like it should be fairly straightforward. 我想要完成的事情似乎应该相当简单。 I have placed a sample project here . 在这里放了一个示例项目。

I have a NSArrayController filled with an array of NSDictionaries. 我有一个NSArrayController充满了NSDictionaries数组。

[[self controller] addObject:@{ @"name" : @"itemA", @"part" : @"partA" }];
[[self controller] addObject:@{ @"name" : @"itemB", @"part" : @"partB" }];
[[self controller] addObject:@{ @"name" : @"itemC", @"part" : @"partC" }];

I am populating a NSPopupButton with the items in this array based on the 'name' key. 我正在使用'name'键来填充NSPopupButton以及此数组中的项目。 This is easily accomplished with the following bindings 使用以下绑定可以轻松完成此操作

绑定

I would then like to populate a NSTextField with the text in the 'part' key based on the current selection of the NSPopupButton. 然后,我想根据NSPopupButton的当前选择,使用'part'键中的文本填充NSTextField。 I have setup the following binding: 我已经设置了以下绑定:

textfieldbindings

With these bindings alone, the text field does display 'partC'. 仅使用这些绑定,文本字段就会显示“partC”。

初始显示

However, if I change the value of the NSPopupMenu, what the text field shows does not change. 但是,如果我更改NSPopupMenu的值,文本字段显示的内容不会更改。

I thought this would simply be a matter of setting up the 'Selected Object' binding on the NSPopupButton 我认为这只是在NSPopupButton上设置'Selected Object'绑定的问题

选定的对象

but that isn't working. 但那不起作用。 I end up with the proxy object in my menu for some strange reason (providing the reason why would be a bonus). 我最终得到了菜单中的代理对象,原因有些奇怪(提供原因可能是奖金)。

窗口2

So, what do I need to do to make this work? 那么,我需要做些什么来使这项工作?

Don't use "Selected Object" in this case. 在这种情况下,请勿使用“选定对象”。 Bind the pop-up's "Selected Index" binding to the NSArrayController's selectionIndex Controller Key. 将弹出窗口的“Selected Index”绑定绑定到NSArrayController的selectionIndex Controller Key。 Tried it out on your sample project and it works. 在你的示例项目上试了一下它就可以了。

EDIT: 编辑:

You asked why it's appropriate to use selectionIndex over selectedObject . 您问为什么在selectedObject上使用selectionIndex是合适的。 First some background: 首先是一些背景:

When binding a popup menu, there are three virtual "Collections" you can bind: Content is the abstract "list of things that should be in the menu" -- you must always specify Content . 绑定弹出菜单时,您可以绑定三个虚拟“集合”: 内容是抽象的“应该在菜单中的事物列表” - 您必须始终指定内容 If you specify neither Content Objects , nor Content Values , then the collection of values bound to Content will be used as the "objects" and the strings returned by their -description methods will be used as the "values". 如果既未指定内容对象 ,也未指定内容值 ,则绑定到Content的值集合将用作“对象”,其-description方法返回的字符串将用作“值”。 In other words, the Content Values are the strings displayed in the pop-up and the Content Objects are the things they correspond to (which are possibly not strings, and which might not have a -description method suitable for generating the text in the pop-up). 换句话说, 内容值是弹出窗口中显示的字符串, 内容对象是它们对应的东西(可能不是字符串,并且可能没有适合在pop中生成文本的-description方法) -up)。 What's important to realize here is that there are potentially three different 'virtual arrays' in play here: The array for Content , the array for Content Objects (which may be different) and the array for Content Values (which may also be different). 这里要认识到的重要一点是,这里可能存在三种不同的“虚拟阵列”: 内容数组, 内容对象数组(可能不同)和内容值数组(也可能不同)。 They will all have the same number of values, and typically, the Content Objects and Content Values will be functions (in the mathematical sense) of the corresponding items in the Content array. 它们都具有相同数量的值,并且通常, 内容对象内容值将是Content数组中相应项的函数(在数学意义上)。

The next thing that's important to realize is that part of NSArrayController 's purpose in life is to keep track of the user's selection. 接下来要认识到的是, NSArrayController的部分目标是跟踪用户的选择。 This is only mildly (if at all) interesting in the case of a pop-up, but starts to become far more interesting in the case of an NSTableView . 在弹出窗口的情况下,这只是温和的(如果有的话)有趣,但在NSTableView的情况下开始变得更有趣。 Internally, NSArrayController keeps track of this by keeping an NSIndexSet containing the indexes in the Content array that are selected at any given time. 在内部, NSArrayController通过保留包含在任何给定时间选择的Content数组中的索引的NSIndexSet跟踪这一情况。 From there, selection state is exposed in several different ways for your convenience: 从那里开始,选择状态以几种不同的方式暴露出来以方便您:

  • selectionIndexes is as described - an NSIndexSet containing the indexes of the selected items in the Content array selectionIndexes NSIndexSet - 一个NSIndexSet包含Content数组中所选项的索引
  • selectionIndex is a convenient option for applications that do not support multiple selection. 对于不支持多选的应用程序, selectionIndex是一个方便的选项。 It can be thought of as being equivalent to arrayController.selectionIndexes.firstIndex . 可以认为它等同于arrayController.selectionIndexes.firstIndex
  • selectedObject is also useful in single selection cases, and corresponds conceptually to ContentObjectsArray[arrayController.selectionIndexes.firstIndex] selectedObject在单选案例中也很有用,并且在概念上对应于ContentObjectsArray[arrayController.selectionIndexes.firstIndex]
  • selection returns a special object (opaque to the consumer) that brokers reads and writes back to the underlying object (or objects in the case of multiple selection) in the Content Array of the array controller. selection返回一个特殊对象(对于使用者不透明),代理在阵列控制器的内容数组中读取和写回底层对象(或多个选择中的对象)。 It exists to enable editing multiple objects at a time in multiple selection cases, and to provide support for other special cases. 它的存在是为了在多个选择案例中一次编辑多个对象,并为其他特殊情况提供支持。 (You should think of this property as read-only; Since its type is opaque to the consumer, you could never make a suitable new value to write into it. It's meaningful to make calls like: -[arrayController.selection setValue: myObject forKey: @"modelKey"] , but it's not meaningful to make calls like -[arrayController setValue: myObject forKey: @"selection"] (您应该将此属性视为只读;因为它的类型对于使用者来说是不透明的,所以您永远不能创建一个合适的新值来写入它。调用如下调用是有意义的: -[arrayController.selection setValue: myObject forKey: @"modelKey"] ,但调用像-[arrayController setValue: myObject forKey: @"selection"]这样没有意义

With that understanding of the selection property, let's take a step back and see why it's not the right thing to use in this case. 通过对selection属性的理解,让我们退后一步,看看为什么在这种情况下使用它不正确。 NSPopUpButton tries to be smart: You've provided it with a list of things that should be in the menu via the Content and Content Values bindings. NSPopUpButton试图变得聪明:您已经通过内容内容值绑定为它提供了菜单中应该包含的内容列表。 Then you've additionally told it that you want to bind its Selected Object to the the NSArrayController 's selection property. 然后你还告诉它你要将它的Selected Object绑定到NSArrayControllerselection属性。 You're probably thinking of this as a "write only" binding -- ie "Dear pop-up, please take the user's selection and push it into the arrayController", but the binding is really bi-directional. 您可能认为这是一种“只写”绑定 - 即“亲爱的弹出窗口,请将用户选择并将其推入arrayController”,但绑定实际上是双向的。 So when the bindings refresh, the popup first populates the menu with all the items from the Content/Content Values bindings, and then it says, "Oh, you say the value at arrayController.selection is my Selected Object . That's odd -- it's not in the list of things bound with my Content/Content Values bindings. I'd better add it to the list for you! I'll do that by calling -description on it, and plunking that string into the menu for you." 因此,当绑定刷新时,弹出窗口首先使用Content / Content Values绑定中的所有项填充菜单,然后它说:“哦,你说arrayController.selection的值是我的Selected Object 。这很奇怪 - 它是不在与我的内容/内容值绑定绑定的事物列表中。我最好将它添加到列表中!我会通过调用-description ,并将该字符串插入菜单中来实现。“ But the object you get from that Selected Object binding is the opaque selection object described above (and you can see from the outcome that it is of class _NSControllerObjectProxy , a private-to-AppKit class as hinted by the leading underscore). 但是你从Selected Object绑定得到的对象是上面描述的不透明选择对象(你可以从结果中看到它是类_NSControllerObjectProxy ,一个私有到AppKit类,由前导下划线暗示)。

In sum, that's why binding your popup's Selected Object binding to the array controller's selection controller key is the wrong thing to do here. 总之, 这就是为什么将弹出窗口的Selected Object绑定绑定到数组控制器的selection控制器键是错误的做法。 Sad to say, but as I'm sure you've discovered, the documentation for Cocoa bindings only begins to scratch the surface, so don't feel bad. 说来可悲,但我敢肯定你已经发现,可可绑定的文档仅开始划伤表面,所以不心疼。 I've been working with Cocoa bindings pretty much daily, in a large-scale project, for several years now, and I still feel like there are a lot of use cases I don't yet fully understand. 我几乎每天都在使用Cocoa绑定,在一个大型项目中,已经好几年了,我仍然觉得有很多用例我还没有完全理解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM