How Can I Add Item to macOS NSComboBox with Xamarin & C#?

berkbababerkbaba TRMember ✭✭

I'm using Xamarin & C# to develop a macOS application. I have a NSComboBox in the storyboard. It have an outlet, so i can access to it successfully.

I have an data context which populated in a list like this:

public static List<string> bloomTypes_EN = new List<string>(new string[] {
        "Cognitive Memory",
        "Cognitive Understanding",
        "Cognitive Practice",
        "Cognitive Analysis",
        "Cognitive Evaluation",
        "Cognitive Generation",
        "Affective Reception",
        "Affective Behavior",
        "Affective Valuing",
        "Affective Organization",
        "Affective Character Making",
        "Psychomotor Perception",
        "Psychomotor Organization",
        "Psychomotor Guided Behavior",
        "Psychomotor Mechanization",
        "Psychomotor Complex Behavior",
        "Psychomotor Harmony",
        "Psychomotor Generation" });

I want add this list into the NSComboBox with Add function:

 if(EarnArea_ComboBox.Count !=  0) // If not empty.
        {
            EarnArea_ComboBox.RemoveAll(); // delete all items.
        }
        else // Empty.
        {
            EarnArea_ComboBox.Add(values.ToArray());
        }

Add functions supports add NSObject[]. Giving string array causes this error:

Error CS1503: Argument 1: cannot convert from 'string[]' to 'Foundation.NSObject[]' (CS1503)

How can I add item to NSComboBox ? Thanks.

Best Answer

  • berkbababerkbaba TR ✭✭
    edited December 2017 Accepted Answer

    Solution is:

    Lots of Cocoa (and iOS) controls have DataSource properties that allow column/row based data to be presented, selected, searched, etc...

    So create a NSComboBoxDataSource subclass and let it accept a List in its .actor:

    public class BloomTypesDataSource : NSComboBoxDataSource
    {
        readonly List<string> source;
    
        public BloomTypesDataSource(List<string> source)
        {
            this.source = source;
        }
    
        public override string CompletedString(NSComboBox comboBox, string uncompletedString)
        {
            return source.Find(n => n.StartsWith(uncompletedString, StringComparison.InvariantCultureIgnoreCase));
        }
    
        public override nint IndexOfItem(NSComboBox comboBox, string value)
        {
            return source.FindIndex(n => n.Equals(value, StringComparison.InvariantCultureIgnoreCase));
        }
    
        public override nint ItemCount(NSComboBox comboBox)
        {
            return source.Count;
        }
    
        public override NSObject ObjectValueForItem(NSComboBox comboBox, nint index)
        {
            return NSObject.FromObject(source[(int)index]);
        }
    }
    

    Now you can apply this to your NSComboBox:

    EarnArea_ComboBox.UsesDataSource = true;
    EarnArea_ComboBox.DataSource = new BloomTypesDataSource(bloomTypes_EN);
    

    Thanks @sushihangover for the solution.

Answers

  • XavierFortinXavierFortin USMember ✭✭

    Have you tried converting your string to NSString? Like so:

    EarnArea_ComboBox.Add(values.Select(str => new NSString(str)).ToArray());

    I usually use data binding, so I haven't tested it myself.

  • berkbababerkbaba TRMember ✭✭
    edited December 2017 Accepted Answer

    Solution is:

    Lots of Cocoa (and iOS) controls have DataSource properties that allow column/row based data to be presented, selected, searched, etc...

    So create a NSComboBoxDataSource subclass and let it accept a List in its .actor:

    public class BloomTypesDataSource : NSComboBoxDataSource
    {
        readonly List<string> source;
    
        public BloomTypesDataSource(List<string> source)
        {
            this.source = source;
        }
    
        public override string CompletedString(NSComboBox comboBox, string uncompletedString)
        {
            return source.Find(n => n.StartsWith(uncompletedString, StringComparison.InvariantCultureIgnoreCase));
        }
    
        public override nint IndexOfItem(NSComboBox comboBox, string value)
        {
            return source.FindIndex(n => n.Equals(value, StringComparison.InvariantCultureIgnoreCase));
        }
    
        public override nint ItemCount(NSComboBox comboBox)
        {
            return source.Count;
        }
    
        public override NSObject ObjectValueForItem(NSComboBox comboBox, nint index)
        {
            return NSObject.FromObject(source[(int)index]);
        }
    }
    

    Now you can apply this to your NSComboBox:

    EarnArea_ComboBox.UsesDataSource = true;
    EarnArea_ComboBox.DataSource = new BloomTypesDataSource(bloomTypes_EN);
    

    Thanks @sushihangover for the solution.

Sign In or Register to comment.