БлогNot. C#: простое взаимодействие форм в проектах Visual Studio

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


теги: c# учебное программирование

К этой статье пока нет комментариев, Ваш будет первым