Create a simple NSOutlineView data source with MonoMac

I cannot figure out how to create a simple NSOutlineView with two columns and a data structure that is more than 1 level (hierarchy).

I researched this for several days, and all I can find are Objective-C examples that I really can't use for anything.

I understand that there are different templates for this, one of which is a DataSource template. I tried to create a class inherited from NSOutlineViewDataSource, but all that I have, I don't know what I have to do next!

Suppose I would like to display the following class in my NSOutlineView:

public class Person { public string Name {get;set;} // First column public int Age {get;set} // Second column public List<Person> Children {get;set} // Children } 

What will be the most trivial approach to doing this?

+6
source share
2 answers

Get ready ... Independent of the NSOutlineView level in MonoMac!

After hundreds of Google searches, and looking through ObjC, as well as C # code, I finally figured out how to do it! I will post my solution here if someone needs it.

This may or may not be the best way to do this, but it works for me.


Step 1 In the Builder interface, add NSOutlineView. Add 2 columns to it and set their identifier colName and colAge .

Also, while you're on it, add a button to your form.


Step 2 : create an output for NSOutlineView - I named my lvMain because I came from the VCL background. Also create an action for your button (this will be the onClick handler).


Step 3: Save your XIB file and return to Mono - it will update your project file. Now we want to create the model that we want to use for our presentation.

In this example, I will use a simple Person object:

 public class Person:NSObject { public string Name { get; set; } public int Age { get; set; } public List<Person> Children { get; set; } public Person (string name, int age) { Name = name; Age = age; Children = new List<Person>(); } } 

There was nothing complicated there.


Step 4: Create a data source. In this example, this is what I did:

 public class MyDataSource:NSOutlineViewDataSource { /// The list of persons (top level) public List<Person> Persons { get; set; } // Constructor public MyDataSource() { // Create the Persons list Persons = new List<Person>(); } public override int GetChildrenCount (NSOutlineView outlineView, NSObject item) { // If the item is not null, return the child count of our item if(item != null) return (item as Person).Children.Count; // Its null, that means its asking for our root element count. return Persons.Count(); } public override NSObject GetObjectValue (NSOutlineView outlineView, NSTableColumn forTableColumn, NSObject byItem) { // Is it null? (It really shouldnt be...) if (byItem != null) { // Jackpot, typecast to our Person object var p = ((Person)byItem); // Get the table column identifier var ident = forTableColumn.Identifier.ToString(); // We return the appropriate information for each column if (ident == "colName") { return (NSString)p.Name; } if (ident == "colAge") { return (NSString)p.Age.ToString(); } } // Oh well.. errors dont have to be THAT depressing.. return (NSString)"Not enough jQuery"; } public override NSObject GetChild (NSOutlineView outlineView, int childIndex, NSObject ofItem) { // If the item is null, it asking for a root element. I had serious trouble figuring this out... if(ofItem == null) return Persons[childIndex]; // Return the child its asking for. return (NSObject)((ofItem as Person).Children[childIndex]); } public override bool ItemExpandable (NSOutlineView outlineView, NSObject item) { // Straight forward - it wants to know if its expandable. if(item == null) return false; return (item as Person).Children.Count > 0; } } 

Step 5 is the best step: Link the data source and add dummy data! We also want to update our view every time we add a new item. This can probably be optimized, but I'm still in the โ€œOh, my God, workingโ€ zone, so I donโ€™t care now.

  // Our Click Action partial void btnClick (NSObject sender) { var p = new Person("John Doe",18); p.Children.Add(new Person("Jane Doe",10)); var ds = lvMain.DataSource as MyDataSource; ds.Persons.Add(p); lvMain.ReloadData(); } public override void AwakeFromNib () { base.AwakeFromNib (); lvMain.DataSource = new MyDataSource(); } 

I hope this information can help the troubled souls of MonoMac novices like me.

+13
source

It took me a little time to trace this, but Xamarin has an example of how to do it. Here

+2
source

Source: https://habr.com/ru/post/925605/


All Articles