C# - Добавить все элементы управления вводом в список<Controls> в порядке TabIndex

У меня есть форма окна, которая просто существует, чтобы принимать ввод от пользователя, для всех намерений и целей, это просто метка и соответствующее поле ввода (текстовое поле, флажок, текстовое поле маскировки и т. Д.).

Я программно разместил все поля ввода в порядке TabIndex, который оптимален для циклического перемещения по ним таким образом, чтобы соответствовать их расположению (вкладка вниз в каждом столбце входных данных, затем в верхней части следующего столбца).

Человек, для которого я создаю этот проект, предусмотрел, что все текстовые поля будут доступны только по одному, так как предыдущий был заполнен. Это грубый способ сделать это без проверки, но, по сути, что-то вроде этого...

if (String.IsNullOrEmpty(textbox1.Text))
{
    textbox2.Enabled = true
}

Так что это нормально делать с двумя текстовыми полями в этом примере, но форма содержит 28 различных входных данных, так что абсурдная серия операторов if будет только последним средством.

Мои мысли заключались в том, чтобы поместить все входные данные в список, в идеале в том же порядке, что и их табличные индексы. Я пытался сделать это с помощью цикла foreach...

    List<Control> inputsList = new List<Control>();
    public void initialiseControls()
    {
        //control position to insert control into list at specified index
        int cntrlpos = 0;
        //for every control in form
        foreach (Control cntrl in this.Controls)
        {
            //not counting labels (not input fields)
            if (!(cntrl is Label))
            {
                //set list position to equal control's TabIndex
                cntrlpos = cntrl.TabIndex;
                //insert the control into the list at the position reflecting TabIndex
                inputsList.Insert(cntrlpos, cntrl); //<---- Error Occurs

                //ASK TEXTBOX TO OUTPUT LIST POSITION AS TEST
                //foreach (var txtbx in this.Controls.OfType<TextBox>())
                //{
                //    txtbx.Text = Convert.ToString(cntrlpos);
                //}
            }
        }

Как только функция вызывается, выдается исключение, указывающее, что "Индекс должен находиться в границах списка". Когда я поместил точку останова в код, он показал, что cntrlpos равен 29, что больше, чем 28 элементов управления вводом, которые есть в форме.

Я не знаю, куда идти дальше, если кто-то может предложить какой-то совет по приведенному выше коду, чтобы поместить элементы управления в список в правильном порядке (или указать мне в направлении другого метода, чтобы сделать что-то подобное), тогда Я был бы очень признателен.

Спасибо Марк

2 ответа

Чтобы сделать свой список, попробуйте это:

List<Control> inputList =
    (from Control c in getAllControls(this)
     where c.TabStop
     orderby c.TabIndex
     select c).ToList();

Определите метод getAllControls в другом месте в вашем классе формы:

IEnumerable<Control> getAllControls(Control parent)
{
    foreach (Control control in parent.Controls)
    {
        yield return control;
        foreach (Control descendant in getAllControls(control))
            yield return descendant;
    }
}

(Взято и немного изменено из рекурсивного поиска с помощью Linq)

Это позволит вам получить даже вложенные элементы управления (например, панели или групповые блоки).

Вы не можете просто использовать TabIndex в качестве индекса в ваш список, потому что даже такие вещи, как ярлыки, имеют индексы табуляции, что испортит ваши индексы.

Я думаю, ты слишком усложнил это...

Просто используйте Control.GetNextControl:

Извлекает следующий элемент управления вперед или назад в порядке перехода дочерних элементов управления.

Например, только с текстовыми полями:

    private void textBoxes_TextChanged(object sender, EventArgs e)
    {
        Control ctl = (Control)sender;
        if (!String.IsNullOrEmpty(ctl.Text))
        {
            Control next = this.GetNextControl(ctl, true);
            if (next != null)
            { 
                next.Enabled = true;
            }
        }
    }

Очевидно, что вам может потребоваться немного более сложная проверка для некоторых других типов элементов управления в другом обработчике, но вам все равно нужно просто взять следующий элемент управления, чтобы включить его с помощью GetNextControl().

Другие вопросы по тегам