Example of NSTableView auto layout

Hi all I'm at the point of having nearly torn all my hair out. This really shouldn't be that hard.

I've PROGRAMATICALLY created an NSTableView with columns and NSTextFields - I've deliberately kept it to text for now to avoid any weird issues with graphics.

The table view is created from an interface as basically I need to pass in one of about a dozen possible interfaces and have it display the table described by that interface. This is all working bar the table isn't auto laying out at all and text in one field bleeds into the next. At one point during my time when I was working on printing I did manage to get it truncating and showing ellipsis at the end but I've tried and tried and couldn't get back to that.

So I basically have a NSTableView with a bunch of columns the controllers.view gets set from SetupTableView and cells created in the Source Class by calls to GetViewforItem.

I think it has something to do with auto layout settings/constraints/resizing masks etc etc etc etc etc. However I'm at my wits end trying to do what should be the basic default - get the view to auto layout.

NSScrollView SetupTableView()  
    {  
        _tableView = new NSTableView  
        {  
            Identifier = Title,  
            RowSizeStyle = NSTableViewRowSizeStyle.Default,  
            Enabled = true,  
            UsesAlternatingRowBackgroundColors = true,  
            AutoresizesSubviews = true,  
            ColumnAutoresizingStyle = NSTableViewColumnAutoresizingStyle.Sequential,  
            WantsLayer = true,  
            Layer = NewLayer(),  
            Bounds = new CGRect(0, 0, 0, 0),  
            AutoresizingMask = NSViewResizingMask.HeightSizable | NSViewResizingMask.WidthSizable,  
            AllowsMultipleSelection = false,  
            AllowsColumnResizing = true,  
            AllowsColumnSelection = false,  
            AllowsColumnReordering = false,  
            AutosaveName = Title,  
            AutosaveTableColumns = true,  
            TranslatesAutoresizingMaskIntoConstraints = false,  
            Target = Self,  
            DoubleAction = new ObjCRuntime.Selector("ViewDetailsSelector"),  
            Action = new ObjCRuntime.Selector("SetRootPersonSelector:")  
        };  
        var properties = GetGenericType().GetProperties();
        foreach (var property in properties)
        {
            float width = 100;
            string columnTitle = property.Name;
            ColumnDetail[] columnDetail = property.GetCustomAttributes(typeof(ColumnDetail), false) as ColumnDetail[];
            if (columnDetail?.Length == 1)
            {
                columnTitle = columnDetail[0].ColumnName;
                width = columnDetail[0].ColumnWidth;
            }
            var tableColumn = new NSTableColumn
            {
                Identifier = property.Name,
                MinWidth = width,
                Editable = false,
                Hidden = false,
                Title = columnTitle,
                SortDescriptorPrototype = new NSSortDescriptor(property.Name, true),
            };
            view.AddColumn(tableColumn);
        }
        if (info.IsOperatingSystemAtLeastVersion(new NSOperatingSystemVersion(10, 13, 0)))  
            _tableView.UsesAutomaticRowHeights = true; // only available in OSX 13 and above  
        var scrollView = new NSScrollView  
        {  
            DocumentView = _tableView,  
            HasVerticalScroller = true,  
            HasHorizontalScroller = true,  
            AutohidesScrollers = true,  
            WantsLayer = true,  
            Layer = NewLayer(),  
            Bounds = new CGRect(0, 0, 0, 0)  
        };  
       return scrollView;  
    }`

In the source class is this

public override NSView GetViewForItem(NSTableView tableView, NSTableColumn tableColumn, nint row)
    {
        var index = Array.IndexOf(_fieldNames, tableColumn.Identifier);
        if (index < 0 || index > _properties.Length)
            return null;
        var property = _properties[index];
        NSTextAlignment alignment = NSTextAlignment.Left;
        ColumnDetail[] x = property.GetCustomAttributes(typeof(ColumnDetail), false) as ColumnDetail[];
        if (x?.Length == 1)
            alignment = x[0].Alignment;

        if (!(tableView.MakeView(CellIdentifier, this) is NSTextField view))
        {
            view = new NSTextField
            {
                Identifier = CellIdentifier,
                BackgroundColor = NSColor.Clear,
                LineBreakMode = NSLineBreakMode.TruncatingTail,
                Bordered = false,
                Selectable = false,
                Editable = false,
                Alignment = alignment,
                TranslatesAutoresizingMaskIntoConstraints = false,
                AutoresizingMask = NSViewResizingMask.HeightSizable | NSViewResizingMask.WidthSizable
            };
            if (tableView.AutosaveName == "PrintView")
                view.Font = NSFont.SystemFontOfSize(8);
        }
        // Setup view based on the column selected
        if (row >= 0)
        {
            var item = _bindingList[(int)row];
            var propertyValue = _properties[index].GetValue(item);
            view.StringValue = propertyValue == null ? string.Empty : propertyValue.ToString();
        }
        else
            view.StringValue = string.Empty;
        return view;
    }

Answers

  • ShammyLevvaShammyLevva Member ✭✭
    edited December 2018

    BTW I did create an empty storyboard put a view controller on in then a tableview on the view controller changed the column width so the cell showed ellipsis and then saved so I could view the XML.

    The problem is there's a lot of stuff there I'm not sure I need a lot of default stuff clearly and I've tried and tried to pick relevant bits from the XML but am utterly unable to make a simple table behave. I can find nothing that explains what is important and what isn't.

    Surely this is NSTableView 101 there must be SOME examples out there??? I'm getting exceptionally frustrated with the Xamarin Mac stuff that there's almost nothing in the way of explanation and everything is trial and error. PLEASE someone this can't be that hard.

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    Unfortunately, many things with AppKit are more difficult than anyone would think. This is true no what matter programing language you are using to talk to Cocoa.

    This difficulty is doubled when you programmatically create UI elements. As you found, Apple does not provide good "default" init methods that setup items as you would get them from storyboard creation. Sometimes dropping them in a storyboard and looking in the xml is the best path forward.

    You can use the auto layout properties and TranslatesAutoresizingMaskIntoConstraints and assuming you get everything perfect you should get reasonable results. However in some cases you may need to create constraints yourself.

    I unfortunately don't have any particular experience with NSTableView and constrains \ autolayout to be able to help here. I however have run into issues of this type (where standard controls just are not drawing correctly) before and it would not surprise me if you hit a similar case (where the bug is in AppKit).

  • ShammyLevvaShammyLevva Member ✭✭

    Thanks for the useful feedback this Mac programming lark is causing serious bruising to my head and a dent is appearing in my office wall. Sigh. Oh well I'll bash away and see if anything magically works.

Sign In or Register to comment.