C#: простое взаимодействие форм в проектах Visual Studio
Довольно часто окно приложения должно как взаимодействовать с другими окнами (формами), так и получать данные из окон стандартных системных диалогов.
В этой заметке рассмотрим простейшие приёмы взаимодействия форм, старая статья для C++/CLI была вот тут.
Предполагается, что мы умеем создавать нужный тип проекта, перетаскивать компоненты из панели элементов в конструктор форм, а также вставлять функции-обработчики событий двойным кликом по нужному событию в окне свойств компонент.
1. Пример конструирования и программного вызова формы
Код может быть выполнен, например, по нажатию кнопки button1
в главной форме.
Form form2 = new Form (); Button button2 = new Button (); button2.Text = "OK"; button2.Location = new Point (10, 10); form2.Text = "Моё окно"; form2.HelpButton = true; form2.FormBorderStyle = FormBorderStyle.FixedDialog; form2.StartPosition = FormStartPosition.CenterScreen; form2.Controls.Add (button2); form2.ShowDialog ();
Для добавления обработчика нажатия программно сгенерированной кнопки button2
достаточно перед последней строкой кода написать:
button2.Click += new EventHandler (this.button2_Click);
- до того, как будет вызван метод form2.ShowDialog()
или form2.Show()
;
При этом код обработчика размещён в текущем модуле Form1.cs
, например:
private void button2_Click (Object sender, EventArgs e) { MessageBox.Show ("Here"); }
Скачать пример 1 в архиве .zip с проектом C#, Visual Studio 2019 (11 Кб)
2. Вызвать форму из формы
В верхнем меню выберем Проект - Добавить форму - Форма (Windows Forms) - имя Form2.
Добавим код там, где нужно создать и вызвать вторую форму:
static int count; //в классе формы Form1 //... Form2 F2 = new Form2 (); F2.Text = "Form " + ++count; F2.Show ();
Как вариант, может быть реализован и массив форм (или иной контейнер).
Опишем нужные данные в классе формы Form1:
const int MAX_FORMS = 3; //Максимальное количество форм static int FormCount; //Счётчик форм private Form [] forms; //Будущий массив форм
Потом инициализируем данные по событию Load
главной формы:
forms = new Form [MAX_FORMS];
Затем реализуем код для создания очередной формы:
if (FormCount < MAX_FORMS) { forms [FormCount] = new Form2 (); forms [FormCount].Text = "Form " + FormCount; forms [FormCount].Show (); FormCount++; } else { MessageBox.Show ("Все формы созданы"); }
Если мы хотим создавать дочерние формы не отдельно, а внутри родительской формы, то в свойствах Form1
нужно указать, что она "предок" (установить свойство IsMdiContainer = true
), а перед показом дочерней формы оператором forms [FormCount].Show ();
пометить её как потомка Form1
:
forms [FormCount].MdiParent = this;
Скачать пример 2 в архиве .zip с проектом C#, Visual Studio 2019 (13 Кб)
Родительская и дочерняя формы могут легко ссылаться друг на друга, например, если Form1
- родительская форма, а Form2
- дочерняя, родитель может вызвать публичный метод потомка
Form2 activeChild = this.ActiveMdiChild as Form2; if (activeChild != null) { activeChild.ПубличныйМетод (); }
и наоборот:
Form1 parent = this.MdiParent as Form1; if (parent != null) { parent.ПубличныйМетод (); }
3. Наладить взаимодействие двух и более отдельных форм
Пусть имеются 2 формы, Form1
и Form2
, при этом на Form1
располагаются Button
(button1
, будет открывать вторую форму) и Label
(label1
, здесь будем менять текст). На Form2
- button2
, по нажатию на которую будет происходить смена текста в label1
.
3.1. В классе первой формы пропишем ссылку на себя, на форму потомка, предусмотрим их инициализацию в конструкторе Form1
, а также реализуем публичный метод, который будем вызывать из второй формы.
public static Form1 SelfRef { get; set; } public static Form2 ChildRef { get; set; } public Form1 () { InitializeComponent (); SelfRef = this; ChildRef = new Form2 (); } public void set (string text) { label1.Text = text; }
3.2. По нажатию button1
будем показывать имеющийся экземпляр второй формы.
private void button1_Click (object sender, EventArgs e) { if (ChildRef != null) ChildRef.Show (); }
3.3. По клику кнопки в Form2
будем вызывать метод set
первой формы:
private void button2_Click (object sender, EventArgs e) { if (Form1.SelfRef != null) { Form1.SelfRef.set ("hello from form2"); Form1.SelfRef.Show (); this.Hide (); } }
Скачать пример 3 в архиве .zip с проектом C#, Visual Studio 2019 (14 Кб)
Аналогично, передавая в конструктор второй формы ссылку на экземпляр первой формы, мы могли бы получать сообщения от произвольного количества форм.
//Изменённое содержимое класса Form1.cs public static Form1 SelfRef { get; set; } static int Tag; public Form1 () { InitializeComponent (); SelfRef = this; } public void set (string text) { label1.Text = text; } private void button1_Click (object sender, EventArgs e) { Form2 form2 = new Form2 (SelfRef, ++Tag); form2.Show (); }
//Изменённое содержимое класса Form2.cs private Form1 ParentRef; int Tag; public Form2 (Form1 ParentRef, int Tag) { InitializeComponent (); this.ParentRef = ParentRef; this.Tag = Tag; this.Text = "Form " + Tag; } private void button2_Click (object sender, EventArgs e) { if (ParentRef != null) { Form1.SelfRef.set ("hello from form " + Tag); Form1.SelfRef.Show (); } }
4. Загрузка файла в текстовое поле, использование стандартных диалогов
На форму добавлено:
- многострочное поле
textBox1
(MultiLine=true
,Doc = Fill
); - кнопки для открытия (
button1
) и закрытия (button2
) файлов или аналогичные пункты меню; - диалоги
openFileDialog1
иsaveFileDialog1
.
Пример основной части кода класса:
private void открытьToolStripMenuItem_Click (object sender, EventArgs e) { if (openFileDialog1.ShowDialog (this) == DialogResult.OK && openFileDialog1.FileName != null) { try { // Создание экземпляра StreamReader для чтения из файла System.Text.Encoding Coding = System.Text.Encoding.GetEncoding (1251); System.IO.StreamReader Reader = new System.IO.StreamReader (openFileDialog1.FileName, Coding); textBox1.Text = Reader.ReadToEnd (); Reader.Close (); textBox1.Modified = false; } catch (System.IO.FileNotFoundException e1) { MessageBox.Show (e1.Message + "\nНет такого файла", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } catch (Exception e2) { // Отчет о других ошибках MessageBox.Show (e2.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } else { openFileDialog1.FileName = ""; openFileDialog1.Dispose (); } } private void сохранитьToolStripMenuItem_Click (object sender, EventArgs e) { saveFileDialog1.FileName = openFileDialog1.FileName; if (saveFileDialog1.ShowDialog () == DialogResult.OK) { Write (); } } void Write () { try { // Создание экземпляра StreamWriter для записи в файл: System.Text.Encoding Coding = System.Text.Encoding.GetEncoding ("utf-8"); // заказ кодовой страницы UTF-8 System.IO.StreamWriter Writer = new System.IO.StreamWriter (saveFileDialog1.FileName, false, Coding); Writer.Write (textBox1.Text); Writer.Close (); //или System.IO.File.WriteAllText(saveFileDialog1.FileName, textBox1.Text); textBox1.Modified = false; } catch (Exception e) { MessageBox.Show (e.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } private void textBox1_KeyUp (object sender, KeyEventArgs e) { if (Char.IsControl ((char)e.KeyValue) == false) textBox1.Modified = true; } private void Form1_FormClosing (object sender, FormClosingEventArgs e) { if (textBox1.Modified == false) return; DialogResult MBox = MessageBox.Show ("Текст был изменен.\nСохранить изменения?", "Простой редактор", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation); if (MBox == DialogResult.No) return; if (MBox == DialogResult.Cancel) e.Cancel = true; if (MBox == DialogResult.Yes) { if (saveFileDialog1.ShowDialog () == DialogResult.OK) { Write (); return; } else e.Cancel = true; // Передумал выходить } }
Скачать пример 4 в архиве .zip с проектом C#, Visual Studio 2019 (12 Кб)
О разработке MDI-приложения на C# Windows Forms говорится в этой статье.
27.01.2023, 11:57 [353 просмотра]