Komunikacja w aplikacji wielookienkowej. Znaczenie zmiennych globalnych (publicznych)

Materiał jest kontynuacją tematu poprzedniego Aplikacja wielookienkowa, stąd sposobu dodawania kolejnych formatek okien nie będę w tym temacie opisywać. Temat obejmuje zagadnienia wykorzystania zmiennych publicznych w aplikacji wielookienkowej MDI.

Cel: Napisz aplikację wielookienkową przy pomocy której będzie można zamykać lub otwierać okna dzieci z innych okien potomnych oraz wykonując działania na zmiennych publicznych zadeklarowanych w różnych oknach.

Krok 1. Układ komponentów w oknach dzieci

Ze względu na tematyczne podzielenie okien potomnych na dwie grupy w poprzednim temacie układ komponentów w oknach dzieci będzie dobrany pod metodę ich wywołania. Czyli wywołanie bezpośrednie i poprzez instancję klasy okna formatki dziecka.

Okna wywoływane bezpośrednio powinny zawierać układ komponentów jak poniżej

Okno numer 1 (formatka Form2) zawiera dwa komponenty Button. Przy ich pomocy będzie można otwierać okno 2 (Form3) i okno 4 (Form4)

button form2

Okno numer 2 (formatka Form3) zawiera jeden komponent Button, przy pomocy którego zamknie się okno 1 (Form2)

button form3 visual studio

Okno numer 3 (formatka Form4) zawiera jeden komponent Button, przy pomocy którego zamknie się okno 2 (Form3)

button form4

Układ komponentów na formatkach okien wywoływanych przez instancję klasy

Okno pierwsze instancji (formatka Form5) zawiera dwa komponenty Button, przy pomocy których można otworzyć okno 2 instancji (Form6) i okno 4 instancji (Form7)

Okno pierwsze instancji (formatka Form5

Okno 2 instancji (formatka Form6) zawiera po dwa komponenty Label, TextBox i Button.

W komponentach TextBox będzie można wprowadzić zmienne publiczne zapisane w oknie 3 instancji (Form7).

komponentach TextBox

Komponenty Button pozwolą wykonać odpowiednie działanie i pokazać wynik w oknie 3 po jego wywołaniu. Sposób przeprowadzenia tych działań będzie bazować na różnych sposobach obsługi zmiennych publicznych.

Okno 3 instancji (formatka Form7) zawiera dwa komponenty Label. Komponent label1 zawiera statyczny tekst "Wynik działania z okna II". Komponent label2 będzie służyć do przedstawienia tego wyniku

Komponent label

Krok 2. Polecenie otwarcia okna dziecka z innego okna dziecka w metodzie wywołania bezpośredniego

Rozwiązanie oparte jest na wywołaniu publicznej funkcji RobOkno zapisanej w kodzie klasy okna głównego (ojca aplikacji wielookienkowej). Ciało funkcji RobOkno znajduje się w poprzednim temacie

Dla przycisku wywołującego okno 2 (Form3)

Wskazówka:


private void Button1_Click(object sender, EventArgs e)
{
	//rzutuj na uchwyt ojca
	Form1 f = (Form1)this.MdiParent;
	if (f.form3 == null) {
		f.form3 = new Form3();
		f.RobOkno(f.form3, "okno2");
		//lub taką konstrukcję
		//f.RobOkno(f.form3 = new Form3(), "okno2");
	}
	else f.form3.Activate();
}

Dla przycisku wywołującego okno 3 (Form4) przedstawię nieznaczną modyfikację wywołania funkcji RobOkno

Wskazówka:

        
private void Button2_Click(object sender, EventArgs e)
{
	//rzutuj na uchwyt ojca
	Form1 f = (Form1)this.MdiParent;
	if (f.form4 == null)
		f.RobOkno(f.form4 = new Form4(), "okno3");
	else f.form4.Activate();
}

Skompiluj program i sprawdź efekt działania

Krok 3. Zamknięcie okna dziecka z poziomu innego okna dziecka w aplikacji wielookienkowej w metodzie wywołania bezpośredniego

Zamykamy okno 1 (Form2) z okna 2 (Form3). Kod zdarzenia Click dla przycisku button1 w formatce Form3

Wskazówka:


private void Button1_Click(object sender, EventArgs e)
{
	//rzutuj na uchwyt ojca
	Form1 f = (Form1)this.MdiParent;
	//zamknij okno1
	if(f.form2!=null)f.form2.Close();
}

W podobny sposób zamkniemy okno 2 (Form3) z okna 3 (Form4). Kod zdarzenia Click dla przycisku button1 w formatce Form4

Wskazówka:


private void Button1_Click(object sender, EventArgs e)
{
	//rzutuj na uchwyt ojca
	Form1 f = (Form1)this.MdiParent;
	//zamknij okno2
	if (f.form3 != null) f.form3.Close();
}

Skompiluj program i sprawdź efekt działania.

Rozwiązanie dla okien wywoływanych poprzez instancję klasy

Metoda używania instancji jest wygodniejsza przy obsłudze zmiennych i funkcji publicznych pomimo, że wymaga powtórzenia tego samego kodu w kolejnych klasach dodawanych okien dzieci.

Krok 1. Wywołanie okna dziecka z poziomu innego okna dziecka

Kod zdarzenia Click przycisku button1 formatki Form5

Wskazówka:


private void Button1_Click(object sender, EventArgs e)
{
	Form6.Instancja.MdiParent = this.MdiParent;
	Form6.Instancja.Text="Okno II otwarte z okna I";
	Form6.Instancja.Show();
	Form6.Instancja.Activate();
}

Kod zdarzenia Click przycisku button2 formatki Form5

Wskazówka:


private void Button2_Click(object sender, EventArgs e)
{
	Form7.Instancja.MdiParent = this.MdiParent;
	Form7.Instancja.Text = "Okno III otwarte z okna I";
	Form7.Instancja.Show();
	Form6.Instancja.Activate();
}

Skompiluj program i sprawdź efekt działania. Działająca aplikacja pozwoli otworzyć okna dzieci z poziomu okna pierwszego dziecka

Visual studio 2019 c# zdarzenie click MDI

Krok 2. Deklarujemy zmienne publiczne i funkcję publiczną w Form7

W oknie 2 (Form6) będziemy pracować na zmiennych zadeklarowanych w innej klasie. Zmienne te muszą mieć charakter publiczny. Deklarujemy dwie publiczne zmienne typu rzeczywistego

Wskazówka:


public partial class Form7 : Form
{
	public float a, b;

Ze względu na ćwiczeniowy charakter tej aplikacji pokażę dwie metody użycia komponentu Label z poziomu innego okna dziecka. Do tego celu będzie potrzebna publiczna zmienna rzutowania na komponent Label

Wskazówka:


	public float a, b;
	public Label _label2 => label2;

I dla drugiego sposobu- publiczna funkcja

Wskazówka:


public void Dodawanie()
{
	label2.Text = a.ToString()+"+"
				 +b.ToString()+"="
				 +(a + b).ToString();
}

Krok 3. Użycie publicznej funkcji w innej klasie okna dziecka

W zdarzeniu Click przycisku button1 w Form6 odwołamy się do zmiennych a i b oraz funkcji Dodaj z klasy okna Form7. Po przypisaniu im wartości w oknie klasy Form6 wyślemy wynik dodawania do okna Form7. Kod, który to umożliwi może przyjąć poniższą postać

Wskazówka:


private void Button1_Click(object sender, EventArgs e)
{
	Form7.Instancja.a = (float)Convert.ToDouble(textBox1.Text);
	Form7.Instancja.b = (float)Convert.ToDouble(textBox2.Text);
	Form7.Instancja.MdiParent = this.MdiParent;
	Form7.Instancja.Text = "Okno III otwarte z okna II";
	Form7.Instancja.Dodawanie();
	Form7.Instancja.Show();
	Form7.Instancja.Activate();
}

Skompiluj program i sprawdź efekt działania. Prawidłowo działając aplikacja zachowuj się jak poniżej

>private void Button1_Click

Krok 4. Użycie publicznego rzutowania na komponent okna dziecka

Tu przedstawię inne podejście do sterowani zmiennymi zewnętrznej klasy okna dziecka w oknie klasy innego dziecka. Działanie jest bardzo podobne jak w kroku 3, z tą różnicą, że wykorzystujemy bezpośrednio właściwości komponentu poprzez jego rzutowanie.

Kod zdarzenia Click drugiego przycisku button2 formatki Form6 zawiera poniższe wiersze

Wskazówka:


private void Button2_Click(object sender, EventArgs e)
{
	float a = (float)Convert.ToDouble(textBox1.Text);
	float b = (float)Convert.ToDouble(textBox2.Text);
	Form7.Instancja.MdiParent = this.MdiParent;
	Form7.Instancja.Text = "Okno III otwarte z okna II";
	Form7.Instancja._label2.Text= a.ToString() + 
	                              "*" + b.ToString() + 
								  "=" + (a * b).ToString();
	Form7.Instancja.Show();
	Form7.Instancja.Activate();
}

Kompilacja aplikacji pozwoli uzyskać poniższe zachowanie się programu

Click(object sender C# visual studio

Ćwiczenie sprawdzające: Zabezpiecz aplikację przed błędami konwersji

Kody plików formatek okna głownego i okien potomnych

Okno główne

Wskazówka:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace wieleOkien
{
    public partial class Form1 : Form
    {
        public Form2 form2;
        public Form3 form3;
        public Form4 form4;

        public Form1()
        {
            InitializeComponent();
        }

        private void ZamknijToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void Okno1ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //otwarcie jednego konkretnego okna
            //zabezpiecz przed wielokrotnym powielaniem tworzenia okna
            if (form2 == null)
            {
                form2 = new Form2();
                form2.MdiParent = this;
                form2.Tag = "okno1";
                form2.FormClosed += new FormClosedEventHandler(zwolnijUchwyt);
                form2.Show();
            }
            else form2.Activate();
        }
        //uniwersalna funkcja otwierająca nowe okno dla metody pierwszej
        public void RobOkno(Form f, string tag)
        {
            f.MdiParent = this;
            f.Tag = tag;
            f.FormClosed += new FormClosedEventHandler(zwolnijUchwyt);
            f.Show();
            f.Activate();
        }

        public void zwolnijUchwyt(object sender, FormClosedEventArgs e)
        {
            Form f =sender as Form;
            switch (f.Tag.ToString())
            {
                case "okno1": form2 = null; break;
                case "okno2": form3 = null; break;
                case "okno3": form4 = null; break;
            }
        }

        private void Okno2ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //zabezpiecz przed wielokrotnym powielaniem tworzenia okna
            if (form3 == null) RobOkno(form3 = new Form3(), "okno2");
            else form3.Activate();
        }

        private void Okno3ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //zabezpiecz przed wielokrotnym powielaniem tworzenia okna
            if (form4 == null) RobOkno(form4 = new Form4(), "okno3");
            else form4.Activate();
        }
        //Uniwersalna funkcja tworząca instancję okna metoda druga
        void RobOknoInstancji(Form f,string tag)
        {
            f.MdiParent = this;
            f.Tag = tag;
            f.Show();
            f.Activate();
        }

        private void OknoInstancja1ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            RobOknoInstancji(Form5.Instancja, "OknoInstnacj1");
            //przykład wypełnienia metody Text instnacji nowego okna
            Form5.Instancja.Text = "Okno Instancji 1";
        }

        private void OknoInstancja2ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            RobOknoInstancji(Form6.Instancja, "OknoInstnacj2");
            //przykład wypełnienia metody Text instnacji nowego okna
            Form6.Instancja.Text = "Okno Instancji 2";
            Form6.Instancja.Width = this.Width / 2;
            Form6.Instancja.Height = this.Height / 2;
        }

        private void OknoInstancja3ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            RobOknoInstancji(Form7.Instancja, "OknoInstnacj3");
            //przykład wypełnienia metody Text instnacji nowego okna
            Form7.Instancja.Text = "Okno Instancji 3";
            Form7.Instancja.Width = this.Width / 2;
            Form7.Instancja.Height = this.Height / 2;
        }
    }
}

Okno potomne Form2.cs

Wskazówka:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace wieleOkien
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            //rzutuj na uchwyt ojca
            Form1 f = (Form1)this.MdiParent;
            if (f.form3 == null) {
                f.form3 = new Form3();
                f.RobOkno(f.form3, "okno2");
                //lub taką konstrukcję
                //f.RobOkno(f.form3 = new Form3(), "okno2");
            }
            else f.form3.Activate();
        }

        private void Button2_Click(object sender, EventArgs e)
        {
            //rzutuj na uchwyt ojca
            Form1 f = (Form1)this.MdiParent;
            if (f.form4 == null)f.RobOkno(f.form4 = new Form4(), "okno3");
            else f.form4.Activate();
        }
    }
}

Okno potomne Form3.cs

Wskazówka:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace wieleOkien
{
    public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            //rzutuj na uchwyt ojca
            Form1 f = (Form1)this.MdiParent;
            //zamknij okno1
            if(f.form2!=null)f.form2.Close();
        }
    }
}

Okno potomne Form4.cs

Wskazówka:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace wieleOkien
{
    public partial class Form4 : Form
    {
        public Form4()
        {
            InitializeComponent();
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            //rzutuj na uchwyt ojca
            Form1 f = (Form1)this.MdiParent;
            //zamknij okno2
            if (f.form3 != null) f.form3.Close();
        }
    }
}

Okno potomne Form5.cs

Wskazówka:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace wieleOkien
{
    public partial class Form5 : Form
    {
        private static Form5 instancja;
        public static Form5 Instancja {
            get
            {
                //zabezpiecz przed wielokrotnym tworzeniem klasy okna
                if (instancja == null) instancja = new Form5();
                return instancja;
            }
        }
            

        public Form5()
        {
            InitializeComponent();
        }

        private void Form5_FormClosed(object sender, FormClosedEventArgs e)
        {
            //zwolnij uchwyt instancji klasy w momencie zamykania okna
            instancja = null;
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            Form6.Instancja.MdiParent = this.MdiParent;
            Form6.Instancja.Text="Okno II otwarte z okna I";
            Form6.Instancja.Show();
            Form6.Instancja.Activate();
        }

        private void Button2_Click(object sender, EventArgs e)
        {
            Form7.Instancja.MdiParent = this.MdiParent;
            Form7.Instancja.Text = "Okno III otwarte z okna I";
            Form7.Instancja.Show();
            Form6.Instancja.Activate();
        }
    }
}

Okno potomne Form6.cs

Wskazówka:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace wieleOkien
{
    public partial class Form6 : Form
    {
        
        private static Form6 instancja;
        public static Form6 Instancja
        {
            get
            {
                //zabezpiecz przed wielokrotnym tworzeniem klasy okna
                if (instancja == null) instancja = new Form6();
                return instancja;
            }
        }
        public Form6()
        {
            InitializeComponent();
        }

        private void Form6_FormClosing(object sender, FormClosingEventArgs e)
        {
            instancja = null;
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            Form7.Instancja.a = (float)Convert.ToDouble(textBox1.Text);
            Form7.Instancja.b = (float)Convert.ToDouble(textBox2.Text);
            Form7.Instancja.MdiParent = this.MdiParent;
            Form7.Instancja.Text = "Okno III otwarte z okna II";
            Form7.Instancja.Dodawanie();
            Form7.Instancja.Show();
            Form7.Instancja.Activate();
        }

        private void Button2_Click(object sender, EventArgs e)
        {
            float a = (float)Convert.ToDouble(textBox1.Text);
            float b = (float)Convert.ToDouble(textBox2.Text);
            Form7.Instancja.MdiParent = this.MdiParent;
            Form7.Instancja.Text = "Okno III otwarte z okna II";
            Form7.Instancja._label2.Text= a.ToString() + 
			                              "*" + b.ToString() + 
										  "=" + (a * b).ToString();
            Form7.Instancja.Show();
            Form7.Instancja.Activate();
        }
    }
}

Okno potomne Form7.cs

Wskazówka:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace wieleOkien
{
    public partial class Form7 : Form
    {
        public float a, b;
        public Label _label2 => label2;

        private static Form7 instancja;
        
        public static Form7 Instancja
        {
            get{
                if (instancja == null) instancja = new Form7();
                return instancja;
            }
        }
        
        public void Dodawanie()
        {
            label2.Text = a.ToString()+"+"
                         +b.ToString()+"="
                         +(a + b).ToString();
        }
        public Form7()
        {
            InitializeComponent();
        }

        private void Form7_FormClosed(object sender, FormClosedEventArgs e)
        {
            instancja = null;
        }
    }
}
Układ okresowy- kod qr
Układ okresowy

Układ okresowy pierwiastków- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
Alkomat- wirtualny test kod qr
Alkomat- wirtualny test

Alkomat- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
Taklarz- olinowanie stałe kod qr
Olinowanie stałe- kalkulator średnic

Olinowanie stałe- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
przepis na gogfry

Przepis na gofry

zobacz
przepis na bitą śmietanę

Przepis na bitą śmietanę

zobacz