Re: Custom Cell Bindings
Re: Custom Cell Bindings
- Subject: Re: Custom Cell Bindings
- From: Seth Willits <email@hidden>
- Date: Sat, 03 Sep 2011 17:45:20 -0700
On Sep 3, 2011, at 12:44 AM, Quincey Morris wrote:
> Really, I'm sorry if I'm misunderstanding, but I think one of two things is going on here:
>
> 1. You're trying to use a NSCell to modify a value object. That may work fine, but there's a conceptual difference that doesn't fit the way we usually think about these things.
>
> 2. Instead of passing a value object to your custom NSCell, perhaps you should be passing the (mutable) object that the value object is a property of, plus something that identifies the value object (a key, a binding name or perhaps it's implicit in the custom NSCell code). I can't remember offhand, but I presume that you could use the "Value" binding and look up the bound-to object and the binding name (and hence key?) from the NSCell's binding info.
Neither of these is true.
What I'm describing is completely 100% normal NSCell usage. I'm not doing anything hacky or weird or against the convention at all. That's why I said this is similar to text field cell in that the text field cell is used "edit" (not mutate) an *immutable* string and the object on the other side of the binding in the table column is updated with the new value from the text cell.
Let's go with an even simpler example. With a checkbox button cell, you click the button and a whole new value is generated.
So let's say I make my own NSCell subclass which does the same thing. You click on something in the cell and a whole new value is generated. Now how do you get this new value into the original model object, which this value is a property of?
As Ken pointed out in his email, when there's a NSTextFieldCell involved, NSTableView is the field editor's delegate and in the textShouldEndEditing: delegate method, the table view sends the new string off to the binding adaptor which validates and applies the value to the binding. He also said: "For a checkbox button cell, the cell invokes -[NSControl sendAction:to:] on its controlView (the table view) to send its action to its target. In the case I tested, the cell had neither an action or a target, but it still did this. Again, the table view took the responsibility of updating the model value through the binding."
I can understand the internal classes working any way they want to, especially given that all of these views/controls existed before bindings. But what I'm expecting, is that with my custom cell, which through the table column is essentially bound to a property on my model object in the array controller, the table view should be observing objectValue of the cell while a user is interacting with it, and if the cell value changes, it should be (like it does with the standard NSCell subclasses) passing it off to the bindings adapter for validation and application to the binding.
Bindings are *bi*directional, but apparently, when you bind an array controller to a table column when the table column has a custom cell, the binding is really only unidirectional. By that, I mean whenever the model property changes, the table view redraws it with the custom cell, but AFAICT, there's no support for changing the value in the custom cell/table view to have it update the model.
AFAICT, the only way to accomplish updating the model is to either subclass NSTableView to add support to receive a private internal action from the cell to somehow update the value on the binding (I'm not sure how it can be done down that path, actually), or to make the containing view controller receive the action, since it has access to the array controller and the tableview.
Apparently (and somewhat surprisingly) in all the years I've been writing Cocoa code I've never written a custom cell for editing values that wasn't based on one of the standard NSCell subclasses, so I've never had to solve this particular problem.
Some other piecemeal responses:
>> What is not straightforward is if the object value is immutable, how I'm supposed to have the new immutable object in the cell actually update the property of an object in the array controller the table column is bound to.
>
> Isn't this exactly the cell [in the sense of table (row, column), not the sense of NSCell] editing mechanism of NSTableView? IOW, the problem isn't solved at the level of the NSCell, which clearly doesn't have enough information, but at the level of the table, which does. As you're well aware, either the KVC or the data source patterns take care of replacing the immutable value.
Right, it *should*. I expect it to be already taken care of for me by the bindings adapter for the table column, but it's not. For instance, I'm expecting the table view/bindings adaptor/whatever, to be observing the cell's value, so it can update the binding, but nothing is observing or bound to anything on the cell, and no action is triggered on the table view either.
On Sep 3, 2011, at 1:15 AM, Ken Thomases wrote:
> The default implementation of -[NSCell trackMouse:inRect:ofView:untilMouseUp:] takes care of invoking -sendAction:to: for you.
Yes, but the action and target are both nil and the table does not hook the action up to itself to do the right thing, so nothing is done.
--
Seth Willits
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden