InputColItem[] _alterCollForSelectOption(IEnumerable <InputColItem> items, bool winnowNullSelectOption, ref string optionLabel)
        {
            InputColItem nullValueItem = null;

            if (winnowNullSelectOption && ModelTypeIsNullable)               // since at this moment, we're only interested in enums and bools (value types), must be nullable for us to try to extract a pre-existing option value
            {
                bool isBool = MainType == typeof(bool);
                if ((MainType.IsEnum || isBool))
                {
                    // find if there is already a nullable item (but ONLY 1), IF so,
                    // get the optionLabel from that if needed, but also delete it from the list...
                    nullValueItem = items.SingleOrDefault(itm => itm.Value == null);

                    // not going to mess with other types at this time for this, so by this point, it IS a enum or bool list

                    string nullItemOptionLabel = nullValueItem?.Name;

                    if (optionLabel.IsNulle())
                    {
                        optionLabel = nullItemOptionLabel ?? (isBool ? "(Not Set)" : "--Select--");
                    }
                }
            }
            return(items.Where(k => k != null && k != nullValueItem).ToArray());
        }
        public static InputColItem[] GetInputEnumValuesStatic(
            object modelValue,
            Type modelType,
            string htmlFieldPrefix,
            string propertyName,
            IEnumerable <string> enumNames = null,
            IEnumerable values             = null,
            bool countNullAsIsChecked      = true)
        {
            EnumInfo enumInfo = EnumInfo.GetEnumInfo(modelType);

            if (enumInfo == null)
            {
                return(null);
            }

            string[] _enumNames = enumNames?.Select(nm => nm?.HtmlEncode()).ToArray();
            object[] _values    = values?.Cast <object>().ToArray();

            if (_enumNames.IsNulle())
            {
                _enumNames = enumInfo.Names;
            }

            if (_values.IsNulle())
            {
                _values = enumInfo.Values;                 // _enumNames; // need to change, why not use the raw enum values themselves and do object comparisons, but oh well, for now, using string comparison
            }
            // we've got our internal arr based versions, null these two now:
            enumNames = null;
            values    = null;

            if (_enumNames.IsNulle() && _values.IsNulle())
            {
                return(null);
            }
            else if (_enumNames == null || _values == null || _enumNames.Length != _values.Length)
            {
                throw new ArgumentOutOfRangeException("Enum names and values must be of equal length.");
            }

            string idPart1             = htmlFieldPrefix + "_" + propertyName + "_";
            bool   allowStringEquality = false;      // hmmm: this will NEVER be true, given above that requires an enum... modelValue is string;
            string modelValueStr       = null;       // see note just above: modelValue?.ToString();

            var arr = new InputColItem[_enumNames.Length];

            for (int i = 0; i < _enumNames.Length; i++)
            {
                object val  = _values[i];
                var    item = new InputColItem()
                {
                    Name       = _enumNames[i],
                    Value      = val,
                    Id         = idPart1 + val,
                    IsSelected = ObjectIsEqual(modelValue, modelValueStr, val, countNullAsIsChecked, allowStringEquality: allowStringEquality)
                };
                arr[i] = item;
            }
            return(arr);
        }
        public (string optionLabel, InputColItem[]) GetInputCollectionItems(
            bool winnowNullSelectOption,
            string optionLabel  = null,
            BoolNames boolNames = null,
            IEnumerable <InputColItem> items       = null,
            IEnumerable <string> enumNames         = null,
            object selectedValueForModelCollection = null)
        {
            InputModelInfo modelInfo = this;

            if (items != null)
            {
                InputColItem[] _items = items.ToArray();
                if (_items.NotNulle())
                {
                    if (!_items.Any(kv => kv.IsSelected))
                    {
                        throw new NotImplementedException();
                        // RUN to find first selected, if any...
                    }
                    return(optionLabel, _items);
                }
            }

            Type mainTyp        = modelInfo.MainType;
            bool typeIsNullable = modelInfo.ModelTypeIsNullable;

            bool isBool = mainTyp.IsPrimitive && mainTyp == typeof(bool);
            bool isEnum = !isBool && mainTyp.IsEnum;

            if (isBool)
            {
                bool?modelValBool = (bool?)ModelValue;

                BoolNames bn = boolNames ?? DefaultBoolNames;
                if (boolNames != null)
                {
                    bn.HtmlEncodeValues().Merge(DefaultBoolNames);
                }

                var nameValues = new InputColItem[] {
                    new InputColItem(bn.TrueName, true, modelValBool == true),
                    new InputColItem(bn.FalseName, false, modelValBool == false),
                    modelInfo.ModelTypeIsNullable
                                                ? new InputColItem(bn.NotSetName, null, modelValBool == null)
                                                : null,
                };
                var _items = _alterCollForSelectOption(nameValues, winnowNullSelectOption, ref optionLabel);
                return(optionLabel, _items);                  // see note below, can't call with ref setter in return line
            }
            else if (isEnum)
            {
                InputColItem[] _items = GetInputEnumValues(enumNames, values: null, countNullAsIsChecked: true);
                _items = _alterCollForSelectOption(_items, winnowNullSelectOption, ref optionLabel);
                // interesting! - the ref set won't set if called within the return line! so must put this line above
                return(optionLabel, _items);
            }
            else
            {
                object modelValue = modelInfo.ModelValue;
                if (modelValue != null)
                {
                    if (modelValue is IEnumerable <object> arr)
                    {
                        List <InputColItem> kvlist = new List <InputColItem>();

                        bool _allowStringEquality = selectedValueForModelCollection != null &&
                                                    AllowStringBasedEqualityComparison(selectedValueForModelCollection.GetType());

                        foreach (object value in arr)
                        {
                            if (value != null)
                            {
                                string valueName = value.ToString();
                                if (valueName.NotNulle())
                                {
                                    bool isSel = selectedValueForModelCollection == null
                                                                                ? false
                                                                                : ObjectIsEqual(selectedValueForModelCollection, valueName, value, countNullAsIsCheckedMatch: true, allowStringEquality: _allowStringEquality);

                                    var _item = new InputColItem(valueName, value, isSel);
                                    kvlist.Add(_item);
                                }
                            }
                        }
                        return(optionLabel, kvlist.Where(kv => kv != null).ToArray());
                    }
                }
            }
            return(optionLabel, null);
        }