Как увеличить имя объекта в цикле?

У меня 1600 текстовых полей. Я хочу что-то вроде этого:

Textbox1.Text="1"
Textbox2.Text="2"
Textbox3.Text="3"
Textbox4.Text="4"
...

Я знаю, что это не работает, но мне нужен такой цикл:

For i as integer = 0 to 1600  
(textbox+i).text=i  
Next  

Я ничего не мог найти об этом. Я не знаю, возможно ли это. Есть идеи?


person Community    schedule 22.09.2015    source источник
comment
Почему вы не используете массивы?   -  person C.Champagne    schedule 22.09.2015
comment
1600 текстбоксов?? Это винформс?   -  person Ric    schedule 22.09.2015
comment
Конечно, это решение для этого примера. Но я имею в виду, что увеличение имен объектов в цикле возможно. Сосредоточьтесь на этом, не обращайте внимания на пример.   -  person    schedule 22.09.2015
comment
Рик. Это пример. Могу я это сделать?   -  person    schedule 22.09.2015
comment
Я должен спросить... почему у вас 1600 текстовых полей...?   -  person Andrew Mortimer    schedule 22.09.2015
comment
Я использовал 1600 для привлечения внимания. Если у меня 4 текстовых поля, попытка использовать цикл бесполезна, верно?   -  person    schedule 22.09.2015
comment
i.stack.imgur.com/fvdkb.png   -  person user3697824    schedule 22.09.2015


Ответы (5)


For i as integer = 0 to 1600  
   CType(Me.Controls("Textbox" + i.ToString()), TextBox).Text = i.ToString()
Next 

Надеюсь, это сработает.

person newbieProgrammer    schedule 22.09.2015
comment
Преобразуйте свой i в строку, @newbieProgrammer. Кроме того, вы можете пропустить шаг, перейдя непосредственно к заданию, например: CType(Me.Controls("Textbox"+(i).ToString()), TextBox).Text = (i).ToString(). Где-то там. - person Paul; 22.09.2015
comment
& исправляет синтаксическую ошибку, но есть ошибка времени выполнения для text1.text = i : NullReferenceException не было обработано. - person ; 22.09.2015
comment
Ваше исключение нулевой ссылки, вероятно, связано с тем, что цикл запускает 0 вместо 1 - person Matt Wilko; 22.09.2015
comment
Проблема в том, что может не быть текстового поля с именем text0 или text1, например. этот код не обеспечивает обработку ошибок. - person Ric; 22.09.2015
comment
который будет искать текстовые поля 1601 - person user3697824; 22.09.2015
comment
измените Me на объект формы, содержащей текстовые поля. - person newbieProgrammer; 22.09.2015
comment
Да, изменил 0 на 1 и все работает. Спасибо всем, этот код работает! - person ; 22.09.2015
comment
@Ric: Это просто фрагмент, показывающий процесс перебора 1600 (в данном случае 1601!) текстовых полей. Я уверен, что ОП сможет выяснить, для каких чисел ему нужно установить атрибут Text. OP также указывает линейный набор элементов управления (TextBox1, TextBox2... и т.д.). Обработка ошибок может быть кувалдой и ореховой областью для этой простой демонстрации. - person Paul; 22.09.2015
comment
@Paul, лол, да, я понял, я просто обрабатываю ошибки, не задумываясь об этом. - person Ric; 22.09.2015

Если вы хотите выполнить цикл из предопределенного диапазона значений, то это должно помочь:

For i = 1 to 1600
    Dim txt As TextBox = TryCast(Me.Controls("TextBox" & i.ToString), TextBox)
    If txt IsNot Nothing
        txt.Text = i.ToString()
    End If
Next
person Ric    schedule 22.09.2015
comment
Разве Find не возвращает массив? - person Andrew Mortimer; 22.09.2015
comment
Ошибка: не указан аргумент для параметра «searchAllChildren» «Общедоступной функции поиска (ключ в виде строки, searchAllChildren в виде логического значения) в виде System.Windows.Forms.Control()». - person ; 22.09.2015

Прежде всего, давайте перечислим все текстовые поля:

var textboxes = this.Controls.OfType<TextBox>()
                             .ToArray();

Теперь, когда у нас есть текстовые поля, давайте переберем их и установим их количество:

for(int i = 0; i < textboxes.Count(); i++)
{
  var textbox = textboxes[i];
  textbox.Text = i.ToString();
}
person Cameron    schedule 22.09.2015
comment
Это будет повторять элементы управления много раз. Если вы так .Select((c,i)=>new {Control=c,Index=i}), то foreach над коллекцией, вы получите значение индекса и только один раз будете взаимодействовать с коллекцией. - person Matthew Whited; 22.09.2015
comment
Каждый вызов .Count() может снова взаимодействовать с набором. Вам лучше использовать .Length или еще лучше установить переменную для подсчета перед for или использовать foreach - person Matthew Whited; 22.09.2015
comment
Вы правы в том, что он будет перебирать коллекцию элементов управления несколько раз, но вызов ToArray() будет оценивать операторы LINQ. Каждый вызов Count() не будет повторять набор снова. Этот метод расширения проверяет, является ли перечисляемый массив массивом или списком. Если бы я выбрал List<T, свойства Count() и Length были бы другими. Тот факт, что это менее эффективный подход, не означает, что это не решение. - person Cameron; 22.09.2015
comment
Я не голосовал против вас. Я просто сказал, что есть гораздо лучшие способы сделать это. В вашем примере он все равно будет дважды зацикливать список. (Возможно, вы получили отказ, потому что они попросили VB.Net, и вы ответили на С#) - person Matthew Whited; 22.09.2015
comment
А.. Это имеет смысл. У меня в голове есть внутренний преобразователь VB в C#. Я на самом деле даже не заметил, пока вы не упомянули об этом. - person Cameron; 22.09.2015
comment
Я должен признать, что нет особого смысла создавать новый массив, когда объекты уже находятся в одном; немного пустой траты памяти, особенно когда вы можете напрямую обратиться к именованному объекту и привести его. - person Paul; 23.09.2015

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

e.g:

For tb As Integer = 1 To 1600
    Dim textBox As TextBox = GetTextBoxByReflection("TextBox" & tb.ToString())
    textBox.Text = tb.ToString()
Next

См. также Получение переменной по имени в C#

person simonalexander2005    schedule 22.09.2015
comment
Пожалуйста, не публикуйте C# в качестве предлагаемого ответа на вопрос с тегом VB.NET. - person Matt Wilko; 22.09.2015
comment
Отражение, безусловно, очень медленный способ сделать это? - person Paul; 22.09.2015

Вы также можете зациклить все элементы управления...

    Dim tb As TextBox
    For Each ctrl As Control In form1.Controls
        If ctrl.GetType.ToString = GetType(TextBox).ToString Then
            tb = CType(ctrl, TextBox)
            tb.Text = ctrl.ID.Substring(7)
        End If
    Next
person Daniel Longieliere    schedule 25.09.2015