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 [3023 просмотра]

