Search code examples
monoxamarin.iosuipickerview

How does one change the number of components (columns) in a UIPickerView using MonoTouch?


Using objC, it seems that there is a method called numberOfComponentsInPickerView which you can use to change the number of components in a UIPickerView. Once this is used to change the number of components you would then reload the components to "refresh" the Picker. i.e. [picker reloadAllComponents];

My question is how would I do this using MonoTouch? I am new to Mono, and after searching through all the methods and properties on my picker object, I can't seem to find this method.

Here is how I am creating my UIPickerView:

public class PeopleModel : UIPickerViewModel {
        static string [] names = new string [] {
            "item1",
            "item2",
            "item3",
            "item4",
            "item5",
            "Custom"
        };

        ActionSheetPickerExampleViewController pvc;
        public PeopleModel (ActionSheetPickerExampleViewController pvc) {
            this.pvc = pvc;
        }

        public override int GetComponentCount (UIPickerView v)
        {
            return 2;
        }

        public override int GetRowsInComponent (UIPickerView pickerView, int component)
        {
            if (component == 0) {
                return names.Length;
            } else {
                return 50;
            }
        }

        public override string GetTitle (UIPickerView picker, int row, int component)
        {
            if (component == 0)
                return names [row];
            else
                return row.ToString ();
        }

        public override void Selected (UIPickerView picker, int row, int component)
        {
            pvc.diskLabel.Text = String.Format ("{0} - {1}",
                                            names [picker.SelectedRowInComponent (0)],
                                            picker.SelectedRowInComponent (1));
            Console.WriteLine (names[picker.SelectedRowInComponent(0)]);
            if (names [picker.SelectedRowInComponent(0)] == "Custom") {
                Console.WriteLine ("Custom selected!");
                picker.ReloadComponent(1);
                using(var alert = new UIAlertView("Select value", "Select custom disk speed",null,"OK","Button2"))
                {
                    alert.Show ();
                }

            }
        }

        public override float GetComponentWidth (UIPickerView picker, int component)
        {
            if (component == 0)
                return 240f;
            else
                return 40f;
        }

        public override float GetRowHeight (UIPickerView picker, int component)
        {
            return 40f;
        }
    }

So the above is the class, then I am creating the picker on an action sheet like this:

actionSheetPicker = new ActionSheetPicker (this.View);
        actionSheetPicker.Title = "Choose disk speed:";
        actionSheetPicker.Picker.Model = new PeopleModel (this);
        actionSheetPicker.Picker.Hidden = false;

Essentially, I am looking at adding another component to this Picker, only when the value of "Custom" is selected in the first component column, and then allowing the user to choose a value from this component as long as "Custom" is selected in the first component. Is this possible? I know how to change the number of components before the picker is created by returning a different number with "GetComponentCount", it is just changing this on the fly once the picker is already created, that I am unsure of.

Thanks for any assistance!


Solution

  • I made a few changes to your PeopleModel to track if Custom is selected, and if it is showing a third component:

    public class PeopleModel : UIPickerViewModel
        {
            bool _custom;
            static string[] names = new string [] {
                "item1",
                "item2",
                "item3",
                "item4",
                "item5",
                "Custom"
            };
    
            ActionSheetPickerExampleViewController pvc;
            public PeopleModel (ActionSheetPickerExampleViewController pvc) {
                this.pvc = pvc;
            }
    
            public override int GetComponentCount (UIPickerView v) {
                if (_custom)
                    return 3;
                return 2;
            }
    
            public override int GetRowsInComponent (UIPickerView pickerView, int component) {
                if (component == 0) {
                    return names.Length;
                } else if (component == 1) {
                    return 50;
                } else
                    return 3;
            }
    
            public override string GetTitle (UIPickerView picker, int row, int component) {
                if (component == 0)
                    return names [row];
                else if (component == 1)
                    return row.ToString ();
                else
                    return row.ToString ();
            }
    
            public override void Selected (UIPickerView picker, int row, int component) {
                pvc.diskLabel.Text = String.Format ("{0} - {1}",
                                                    names [picker.SelectedRowInComponent (0)],
                                                    picker.SelectedRowInComponent (1));
                Console.WriteLine (names [picker.SelectedRowInComponent (0)]);
                _custom = names [picker.SelectedRowInComponent (0)] == "Custom";
                picker.ReloadAllComponents ();
    
            }
    
            public override float GetComponentWidth (UIPickerView picker, int component) {
                if (component == 0)
                    return 240f;
                else
                    return 40f;
            }
    
            public override float GetRowHeight (UIPickerView picker, int component) {
                return 40f;
            }
        }
    

    I think this is what you were trying to accomplish. The method ReloadAllComponents() is a member of UIPickerView.