3

Существует у меня квадрат из кнопок, размером 5х5 в WinForms.
Есть у меня и двумерный массив, куда и нужно поместить все 25 кнопок(с учётом местонахождения, конечно), для дальнейшего перебора и изменения параметров.
Вопрос: Как наиболее эффективно поместить кнопки за названиями btn1, btn2... в двумерный массив. Я, конечно, могу их ручками поместить в массив, но 25 строк писать для этого не кажется хорошим решением. Что можно сделать или изменить(что-то в массиве, например), для хорошего решения?

Ilya
  • 67
  • Научитесь писать циклы. Дополнительно может пригодится нахождение кнопки по имени или перебор коллекции кнопок. Например, что-то типа тынц1 и тынц2 – A K Jun 17 '21 at 14:58
  • Ну хорошо. Предположим, я буду использовать два цикла for. Если по двумерному массиву я представляю как пройтись, что мне делать с кнопками? Как их поместить автоматически в массив?

    P.S: Увидел правку, сейчас посмотрю.

    – Ilya Jun 17 '21 at 15:01
  • А этого вы не объяснили сами. У вас судя по тексту вопроса ОДИН ряд кнопок (слово "один" пропущено, но легко восстанавливается). Как записать ОДИН ряд в двумерный массив -- вам решать. Ладно бы вы сказали, что у вас кнопок в несколько рядов и нужно их также в двумерный массив записать, как-то преобразуя координаты. Но похоже что вы и сами не особо понимаете чего хотите добиться. Может быть хотели ОДИН ряд кнопок в одномерный массив записать, не? – A K Jun 17 '21 at 15:04
  • Нет, как раз рядов несколько. У меня квадрат 5х5 из кнопок(25 кнопок). То есть 5 рядов кнопок. Сейчас исправлю, "Ряд" у меня здесь в смысле "несколько". – Ilya Jun 17 '21 at 15:09
  • Тогда вам нужно в цикле получать координаты X, Y каждой кнопки и на их основании вычислять индекс в двумерном массиве. Разумеется, это возможно, если у вас кнопки расставлены строго по сетке: известна ширина и высота кнопки и расстояние между элементами по горизонтали и вертикали. Рисуйте клеточки, думайте над формулой. Возможно, для начала проще будет решить обратную задачу: из имеющегося массива создать кнопки на форме, а потом до вас дойдёт как решить исходную задачу. – A K Jun 17 '21 at 15:13
  • Да, они стоят по порядку. Сейчас ещё сумел найти на примере ваших ссылок вариант решения с this.Controls("btn" + i.ToString()), попробую помутить с названиями кнопок и написать так. Если не получится - попробую воспользоваться вашим вариантом. – Ilya Jun 17 '21 at 15:17
  • Был ли мой ответ полезен? – aepot Jun 19 '21 at 22:31
  • 1
    @aepot Извините, не увидел, так как на тот момент смог решить задачу через Controls.Find(), пока времени нету что написать свой вариант здесь. Ваш, в вероятно, более правильный подход, ибо я сделал через имена (это было учебное задание, поэтому такая логика подошла). Хотя его попробовать смогу только позже. В любом случае, спасибо за ответ. – Ilya Jun 21 '21 at 06:22

1 Answers1

3

Когда интерфейс хранит данные - это как хвост виляет собакой.

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

К примеру, создадим класс данных.

public class ButtonInfo
{
    public Point Location { get; set; }
    public string Text { get; set; }
}

Заполним к примеру его тестовыми данными и нарисуем на форме кнопки, пусть нам нужно нарисовать клавиатуру для калькулятора.

Я создал новый проект и написал такой код

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
private void Form1_Load(object sender, EventArgs e)
{
    // создаем массив
    ButtonInfo[] buttons = new ButtonInfo[12];

    // заполняем массив
    for (int i = 0; i < buttons.Length; i++)
    {
        buttons[i] = new ButtonInfo 
        { 
            Location = new Point(i % 3 * 100 + 10, i / 3 * 100 + 10),
            Text = i switch 
            { 
                < 9 => (i + 1).ToString(),
                9 => "±",
                10 => "0",
                11 => ",",
                _ => "Кнопка"
            } 
        };
    }

    // выводим кнопки на форму
    for (int i = 0; i < buttons.Length; i++)
    {
        Button btn = new Button 
        { 
            Text = buttons[i].Text, 
            Location = buttons[i].Location, 
            Size = new Size(90, 90),
            Font = new Font("Segoe UI", 24, FontStyle.Regular, GraphicsUnit.Point)
        };
        btn.Click += Btn_Click;
        this.Controls.Add(btn);
    }
}

// при нажатии на любую кнопку сработает этот обработчик события
private void Btn_Click(object sender, EventArgs e)
{
    Button btn = (Button)sender;
    MessageBox.Show($"Нажата кнопка '{btn.Text}'");
}

}

На форме выглядит это так

введите сюда описание изображения

При нажатии на кнопку выскакивает сообщение

введите сюда описание изображения

Решение вашего вопроса заключается в хранении и передаче массива ButtonInfo[]. А на основе этого массива вы сможете сгенерить этот же интерфейс в любой форме. И не потребуются никакие имена для кнопок. Если название Text кнопки не подходит для идентификации самой кнопки или у вас несколько кнопок с одинм и тем же текстом, используйте например Button.Tag, записывая туда то что нужно, и считывайте значение в обработчике события.

А контролы должны жить на форме, их не нужно никуда переносить и нигде хранить. К тому же когда форма закроется, она задиспозит все созданные вами кнопки и вы больше не сможете их нигде использовать.

aepot
  • 49,560