How to transfer the selected text parameters from the second form to the first one, by pressing the "apply" button in the second form, without violating the principles of OOP?

Form1:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void font_button_Click(object sender, EventArgs e) { Form2 font_dialog = new Form2(); font_dialog.ShowDialog(); } private void textBox1_TextChanged(object sender, EventArgs e) { } // Кнопка сохранения файла в заранее указанную папку private void save_button_Click(object sender, EventArgs e) { Directory.CreateDirectory("C:\\my_dir"); // Создание директории // Запись string lines = "" + textBox1.Text; File.WriteAllText(@"C:\\my_dir\my_txt.txt", lines); MessageBox.Show("Файл сохранен!"); } private void exit_button_Click(object sender, EventArgs e) { this.Close(); } } } 

Form2:

 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form2 : Form { public Form2() { InitializeComponent(); } // Список шрифтов private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { switch (comboBox1.Text) { case "Arial": Font font_1 = new Font("Arial", this.Font.Size); comboBox1.Font = font_1; break; case "Courier New": Font font_2 = new Font("Courier New", this.Font.Size); comboBox1.Font = font_2; break; case "Times New Roman": Font font_3 = new Font("Times New Roman", this.Font.Size); comboBox1.Font = font_3; break; default: Font def_font = new Font("Arial", this.Font.Size); comboBox1.Font = def_font; break; } } // Кнопка применения параметров шрифта private void OK_Click(object sender, EventArgs e) { } private void numericUpDown1_ValueChanged(object sender, EventArgs e) { } } } 
  • Yes, an idea with three hard-letter fonts and a textbox is at least strange. - Qwertiy

3 answers 3

IMHO, the proposed version of the global FormValuesHolder contradicts all the principles of OOP: it adds temporary connectivity between objects and can lead to maintenance problems.

  • The decision violates the principle of encapsulation . Where is the information hiding? An open field without behavior does not contribute to information hiding.

  • Lack of abstraction . A static field does not increase the level of abstraction.

  • Lack of behavior . OOP data is not stored by itself. Some behavior must be associated with them. The behavior of the property of type string in terms of modeling solutions is missing.

Now, an alternative solution.

  1. If pressing the "apply" button of the second form closes it.

In this case, in the Form2 class it is enough to announce the open properties of the required type and set it in the OK_Click event:

 public partial class Form1 : Form { private void font_button_Click(object sender, EventArgs e) { Form2 font_dialog = new Form2(); if (font_dialog.ShowDialog() == DialogResult.OK) { // Мы знаем, что кнопка OK была нажата, пользователь // не отменил ввод. // Используем новые свойства шрифта Console.WriteLine(font_dialog.NewFont); } } } 

Usually the first option is suitable, because the OK button usually closes the form.

But if, for some unknown reason, this option does not fit, then you can add an event to the second form that will be generated when you select a new font.

 // Да, имена форм тоже разумно сразу же давать осмысленные public partial class MainForm : Form { public void FontButtonClick(object sender, EventArgs e) { // Да, подчеркивания не приветствуются в именах полей/переменных var fontDialog = new FontDialog(); fontDialog.NewFontSelected += HandleNewFont; fontDialog.ShowDialog(); } private void HandleNewFont(object sender, NewFontSelectedEventArgs ea) { // Обратаываем выбранный новый шрифт } } public class NewFontSelectedEventArgs : EventArgs { public string NewFont {get; set;} } public partial class FontDialogForm : Form { public event EventHandler<NewFontSelectedEventArgs> NewFontSelected; private void OnNewFontSelected(string newFont) { var handler = NewFontSelected; if (handler != null) handler(this, new NewFontSelectedEventArgs{NewFont = newFont}; } // все тоже самое // Кнопка применения параметров шрифта private void OK_Click(object sender, EventArgs e) { // уведомляем подписчиков о выбранном новом шрифте OnNeFontSelected(newFont); } } 

Yes, if you look at the standard FontDialog , you can easily notice in it the similarity with the proposed solution. Here is an example of using the standard dialog to change the font:

 private void button1_Click(object sender, System.EventArgs e) { fontDialog1.ShowColor = true; fontDialog1.Font = textBox1.Font; fontDialog1.Color = textBox1.ForeColor; if(fontDialog1.ShowDialog() != DialogResult.Cancel ) { textBox1.Font = fontDialog1.Font ; textBox1.ForeColor = fontDialog1.Color; } } 

[Cap mode on] No global static classes that contain an intermediate new font! [Cap mode off].

  • Um, I somehow do not see a violation of encapsulation, polymorphism, inheritance and abstraction. This is not a good decision, I do not argue, but is there a violation of the principles of the PLO? There is a violation of the principles of good architecture, which have nothing to do with OOP. - etki
  • As I understand it, this is about my phrase at the beginning of the answer ... A global answer is a non-OO decision. Totally. This is from the world of structured programming. And yes, a global object with an open property breaks the OOP: is it a violation of encapsulation (where is the information hiding?), Lack of abstraction (where is it in this decision?), Lack of behavior (there is only data). So it breaks a lot of things;) - Sergey Teplyakov
  • The existence of the principle of abstraction does not imply its mandatory implementation, as well as with encapsulation. In general, there is a formal setter and getter. - etki
  • So of all the classical principles of the OOP, only inheritance is not violated here, which is not applicable here. In other words, here all the applicable canons of the PLO are violated, and this is not enough for you? - Sergey Teplyakov
  • They are not violated, they are not here, because they are not needed, as well as inheritance. There is no need for abstraction, because there is no multi-level. There is no inheritance here, because the example is banal and there is nothing to inherit. The only field is hidden behind the accessors. - etki

I would say no more about the violation of the PLO, but about the violation of the general principles of program design.

The problem with your code is that business logic and presentation are merged and mixed. As a result, the window for some reason knows about where and how data is stored, although this is actually a question for the model level.

Thus, the correct approach seems to me the following:

  1. The first form requests parameters from its model / VM (depending on the chosen pattern of program organization).
  2. The / VM model detects that this data needs to be requested in the UI, and initiates the display of the second form.
  3. After closing the second form, the model / VM has information, and it is delivered to the first form.
  • one
    This is true, but for very simple cases (like choosing a font), this division, I think, can be ignored. Especially in WinForms, where with MVVM is not so much. - Memoizer
  • @Memoizer: For a simple program, it is not necessary to follow the principles of OOP either. I regarded the code from the question as a simplified example. - VladD
  • @Memoizer for WinForms MVP works very well. - andreycha
  • one
    @Memorize, on the contrary, the code will be simplified if you enter a separate business logic object that will manage the call for forms and collect data. - hardsky
  • one
    @SergeyTeplyakov: Then the answer will be to him "for growth" :-) - VladD

Make a separate static class - storage.

 public static class FormValuesHolder { static string _str1 = string.Empty; public static string Str1 { get { return _str1; } set { _str1 = value; } } } 

And access this field from various forms: FormValuesHolder.Str1

  • five
    Isn't it a global object that violates the key principles of the PLO? - Sergey Teplyakov