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().