I have a fairly basic MainWindow.xib
with a source list-style sidebar. I created it by dragging the Source List template into the window, which already contains two NSTableCellView
s: HeaderCell
and DataCell
.
The latter consists of an icon (using NSImageView
) and a label (NSTextField
). Instead, I want the label and another, smaller label underneath. In IB, this looks as follows:
If I focus on just DataCell
, it highlights accordingly:
Thing is, actually running the program, it looks nothing like the template:
Notice how the two NSTextField
s just get smashed together into one. My understanding was that view-based NSOutlineView
s (and view-based NSTableView
s, for that matter) are supposed to be designed as a template from within IB. Instead, the dimensions from the template seem to get mostly ignored.
Here's the code that sets the view's values from the data source:
public class TourSourceListDelegate : NSOutlineViewDelegate
{
public override bool IsGroupItem(NSOutlineView outlineView, MonoMac.Foundation.NSObject item)
{
return (item as TourSourceListDataSource.Item).IsHeader;
}
public override NSView GetView(NSOutlineView outlineView, NSTableColumn tableColumn, MonoMac.Foundation.NSObject item)
{
if (IsGroupItem(outlineView, item))
{
return outlineView.MakeView("HeaderCell", this);
}
else
{
var data = item as TourSourceListDataSource.Item;
var dataView = outlineView.MakeView("DataCell", this);
(dataView.Subviews[0] as NSTextField).StringValue = data.Name;
(dataView.Subviews[1] as NSTextField).StringValue = data.Date_start.ToShortDateString();
return dataView;
}
}
}
I've tried overriding GetRowHeight
, but that doesn't seem to resolve the problem (it makes more room, but still doesn't let the views distribute themselves properly), nor does it seem necessary.
I've also tried playing with the various Autosizing
, Autoresizes Subviews
, etc. toggles in IB, but that doesn't seem to produce intuitive results, and again, it doesn't seem necessary — the view as presented in IB is exactly what I want, just with slightly longer labels in practice.
I haven't tried converting this to AutoLayout yet.
What obvious step am I missing?
Some more info that probably doesn't make a difference: this is a Xamarin.Mac/MonoMac project with Xcode 5.0, MacOSX10.8.sdk, Xamarin Studio 4.0.12, Xamarin.Mac 4.0.12, and Mono 3.2.3 (targeting Mono / .NET 4.0). I've also enabled App Sandboxing.
What's important in interface builder is the view hierarchy. What kind of view is that cell? Are those labels really subviews of the cellview or not? The hierarchy should look something like:
One thing that's fishy that I see is accessing dataView.Subviews[0]
and [1]
. If you're adding subviews to your cells then should be creating your own NSTableViewCell
subclasses, with each view connecting to the subclass' IBOutlet
properties. The subclass doesn't need any code in its implementation, just the declaration of its properties in @interface
, such as titleField
and descriptionField
, and an empty @implementation
that auto-synthesizes them.
Then makeViewWithIdentifier
(or apprently the glue MakeView
in Xamarin) when passed the right identifier should create your NSTableViewCell
subclass, and at runtime you can verify that using po dataView
in the debugger. Then you access the subviews using the properties of your NSTableViewCell
subclass' interface instead of assuming which view is in which position with the subview array, using dataView.titleField
and dataView.descriptionField
.
If your cell view has one text field then you can use NSTableViewCell
without subclassing, but do connect up the textField
outlet (its connected by default as long as you don't delete & recreate the cell view's label view) so you can access it through the property, again instead of having to dive into the subviews array.
All that said, it's not really clear why you're seeing what you are. It looks like those aren't the subviews you expect, and might even look like the wrong fonts as well as in the wrong positions. Using a custom subclass of NSTableViewCell
and verifying its class at runtime is a good way of making sure it's creating the view you expect, but you can also dump the subview within the debugger using po [dataView _subtreeDescription]
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With