Hvordan åpne en annen fra ett skjema. Legger til skjemaer. Samspill mellom former. Et eksempel på å konstruere og programmere et skjema

Spørsmålet som tas opp i denne artikkelen er mer sannsynlig å forholde seg til emnet å bygge en applikasjonsarkitektur, og ikke spesifikt til problemet som vurderes. Å overføre data fra en form til en annen er ikke vanskelig i det hele tatt. For å gjøre dette er det nok å gjøre kontrollen hvis data vi ønsker å få åpen, det vil si å merke den med den offentlige modifikatoren. Et annet alternativ er også mulig. For eksempel, i den første formen lager vi et objekt av den andre formen ved å sende en referanse til oss selv til konstruktøren, det vil si ved å overføre en referanse til den første fra den første formen til den andre
SecondForm secondForm = ny SecondForm(this);
Naturligvis, før du gjør dette, bør du ta vare på å skape en overbelastning for konstruktøren av den andre formen.

Og denne metoden er ganske vanlig. Men med sin enkelhet har den mange potensielle problemer, den viktigste er et brudd på prinsippet om innkapsling. Kort sagt, den andre formen skal ikke vite noe om eksistensen av den første, og enda mer bør den ikke kunne påvirke den.

Løsningen på dette problemet er ganske enkel. La oss se direkte på koden. Vi skaper i designeren hovedform(det vil bli lansert når applikasjonen starter). La oss sette en Tekstboks, Merkelapp Og Knapp.

Ved å klikke på knappen åpnes det andre skjemaet og teksten fra tekstfelt hovedskjemaet vil bli overført til tekstfeltet i det andre skjemaet. Til å begynne med ser den andre formen slik ut:

I likhet med den første har den de samme kontrollene. Vi trenger ikke mer. Søknadsinngangspunktet starter hovedskjemaet:

Bruke System; bruker System.Collections.Generic; bruker System.Linq; bruker System.Windows.Forms; navneområde From1FormTo2 ( statisk klasse Program ( // Hovedinngangspunktet for applikasjonen. static void Main() ( Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); ) ) )

Hovedskjemakoden ser slik ut:

Bruke System; bruker System.Collections.Generic; bruker System.ComponentModel; bruker System.Data; ved hjelp av System.Drawing; bruker System.Linq; bruker System.Text; bruker System.Windows.Forms; navneområde From1FormTo2 ( offentlig delklasse MainForm: Form ( //second form SecondForm secondForm; //constructor public MainForm() ( InitializeComponent(); ) //dataoverføring hendelsesbehandler //fra hovedskjemaet til det andre private tomrommet btn_mainForm_Click(object sender, EventArgs e) ( secondForm = new SecondForm(tb_mainForm.Text.Trim()); secondForm.ShowDialog(); if (secondForm.DialogResult == DialogResult.OK) tb_mainForm.Text = secondForm.ReturnData(); ) ) )

Følgelig, ikke glem å koble knappen til arrangementet Klikk. Her i hovedformklassen er det et felt SecondForm secondForm, som representerer det andre formobjektet. Når du klikker på "Send"-knappen, opprettes et annet skjema (den overbelastede konstruktøren kalles, vi oppretter den senere) og lanseres ved hjelp av metoden ShowDialog(). I dette tilfellet er denne metoden egnet for oss. Etter dette sørger vi dessuten for å sjekke om det andre skjemaet ble lukket, men klikket på knappen. Hvis en knapp ble klikket på det andre skjemaet, skal det første skjemaet godta data fra det andre. Dette skjer ved å kalle metoden ReturnData() i den andre formen.

Nå er den mest interessante delen koden til den andre formen:

Bruke System; bruker System.Collections.Generic; bruker System.ComponentModel; bruker System.Data; ved hjelp av System.Drawing; bruker System.Linq; bruker System.Text; bruker System.Windows.Forms; navneområde From1FormTo2 ( public partial class SecondForm: Form ( //overloaded constructor public SecondForm(string data) ( InitializeComponent(); tb_secondForm.Text = data; ) //dataoverføring hendelsesbehandler //fra det andre skjemaet til det viktigste private tomrommet btn_secondForm_Click (objektavsender, EventArgs e) ( this.DialogResult = DialogResult.OK; ) // offentlig metode for å få tilgang til // tekstfeltet i dette skjemaet offentlig streng ReturnData() ( return (tb_secondForm.Text.Trim()); ) ) )

Som du kan se, er det en enkelt konstruktøroverbelastning som godtar en strengtype. Husk at vi prøver å overføre tekst fra en tekstboks. I konstruktøren er komponentene planlagt å initialiseres og teksten i tekstfeltet settes til den overførte verdien fra det første skjemaet. Deretter ved å abonnere på arrangementet Klikk for knappen i det andre skjemaet opprettet vi en behandler btn_secondForm_Click, som simulerer operasjonen av "Ok"-knappen i en hvilken som helst dialogboks. Ved å klikke på "Send"-knappen (av det andre skjemaet), utfører vi betingelsen

(secondForm .DialogResult == DialogResult .OK)

Den første formen kaller derfor metoden secondForm.ReturnData(), setter vi tekstfeltet til det første skjemaet til verdien av tekstfeltet i det andre skjemaet.

Jobb denne metoden Jeg tror ikke lenger krever forklaring. Den returnerer ganske enkelt teksten fra et enkelt tekstfelt, samtidig som den holder den privat.

Som et resultat overførte vi data til den andre formen fra den første og fra den andre til den første uten å bryte prinsippene for innkapsling.

Prøv å skrive inn teksten "aaa" i tekstfeltet i det første skjemaet og klikk på knappen. Du vil se denne teksten i tekstfeltet i det andre skjemaet som åpnes. Prøv å endre teksten til "aaa ppp" og klikk på knappen. Du vil se hvordan, etter å ha lukket det andre skjemaet, vil denne teksten vises i tekstfeltet til hovedskjemaet.

Nå tror jeg du vil kunne overføre data mellom skjemaer mer korrekt. I den neste artikkelen vil vi snakke om hvordan du gjør det i ASP.NET-applikasjoner.

Sist oppdatert: 31.10.2015

For å legge til et annet skjema til prosjektet, høyreklikk på prosjektnavnet i Solution Explorer-vinduet og velg Legg til->Windows-skjema...

La oss gi den nye formen et navn, for eksempel, Form2.cs:

Så vi har lagt til et annet skjema til prosjektet vårt. La oss nå prøve å implementere interaksjon mellom to former. La oss si at det første skjemaet vil kalle det andre skjemaet når du klikker på knappen. La oss først legge til en knapp i det første skjemaet, Form1, og dobbeltklikke på knappen for å gå til kodefilen. Så vi blir tatt til knappens klikkhendelsesbehandler, som opprettes som standard etter å dobbeltklikke på knappen:

Privat void button1_Click(objektavsender, EventArgs e) ( )

La oss nå legge til koden for å kalle det andre skjemaet til det. Vår andre form heter Form2, så først lager vi et objekt av denne klassen, og for å vise det på skjermen kaller vi Vis-metoden:

Privat void button1_Click(objektavsender, EventArgs e) ( Form2 newForm = new Form2(); newForm.Show(); )

La oss nå gjøre det motsatte - slik at den andre formen påvirker den første. Mens den andre formen ikke vet om eksistensen av den første. For å fikse dette, må du på en eller annen måte overføre informasjon om det første skjemaet til det andre skjemaet. For å gjøre dette, bruker vi å sende en lenke til skjemaet i konstruktøren.

Så la oss gå videre til det andre skjemaet og gå til dets kode - høyreklikk på skjemaet og velg Vis kode. Foreløpig er den tom og inneholder bare en konstruktør. Siden C# støtter metodeoverbelastning, kan vi lage flere metoder og konstruktører med forskjellige parametere og kalle en av dem avhengig av situasjonen. Så la oss endre kodefilen til det andre skjemaet til følgende:

Bruke System; bruker System.Collections.Generic; bruker System.ComponentModel; bruker System.Data; ved hjelp av System.Drawing; bruker System.Linq; bruker System.Text; bruke System.Threading.Tasks; bruker System.Windows.Forms; navneområde HelloApp ( offentlig delklasse Form2: Form ( public Form2() ( InitializeComponent(); ) public Form2(Form1 f) ( InitializeComponent(); f.BackColor = Color.Yellow; ) ) )

Faktisk har vi nettopp lagt til her ny konstruktør offentlig Form2(Form1 f) der vi får den første formen og setter bakgrunnen til gul. La oss nå gå videre til koden til det første skjemaet, der vi kalte det andre skjemaet og endre det til følgende:

Privat void button1_Click(objektavsender, EventArgs e) ( Form2 newForm = new Form2(this); newForm.Show(); )

Siden nøkkelordet i dette tilfellet representerer en referanse til det gjeldende objektet - Form1-objektet, vil det motta det (lenken) når det opprettes det andre skjemaet og kontrollere det første skjemaet gjennom det.

Nå, etter å ha klikket på knappen, vil et andre skjema bli opprettet, som umiddelbart vil endre fargen på det første skjemaet.

Vi kan også lage objekter av gjeldende form:

Privat void button1_Click(objektavsender, EventArgs e) ( Form1 newForm1 = new Form1(); newForm1.Show(); Form2 newForm2 = new Form2(newForm1); newForm2.Show(); )

Når du arbeider med flere skjemaer, må du ta hensyn til at en av dem er den viktigste – som lanseres først i Program.cs-filen. Hvis vi har en haug med skjemaer åpne samtidig, så lukkes hele applikasjonen når vi lukker det viktigste, og sammen med alle andre skjemaer.

Til tross for at min mening om Microsofts Visual Studio fortsatt er den samme, må du noen ganger gjøre noe med det. Hvis vi kommer overens med at vi faktisk ikke skriver i C++, men i såkalte C++/CLI, vil det å jobbe med kjente visuelle komponenter ikke være så forskjellig fra de samme Borland-miljøene. Men det kan skape problemer, sammenlignet med Builder La oss vurdere 3 typiske situasjoner med å jobbe med en applikasjon som inneholder mer enn ett skjema Eksempelmiljøet er gratis Visual C++ 2010 Express, det antas at hovedformen har standardnavnet Form1.

Et eksempel på å konstruere og programmere et skjema

Denne koden kan utføres for eksempel ved å klikke på en knapp i hovedskjemaet Form1.

Form^form2 = gcnew Form(); Button^ button2 = gcnew Button(); knapp2->Tekst = L"OK"; knapp2->Plassering = Punkt(10,10); form2->Text = L"Mitt vindu"; form2->HelpButton = sant; form2->FormBorderStyle = System::Windows::Forms::FormBorderStyle::FixedDialog; form2->StartPosition = FormStartPosition::CenterScreen; skjema2->Kontroller->Legg til(knapp2); form2->VisDialog();

For å legge til en klikkbehandler for en programmatisk generert knappknapp2, skriv bare før den siste kodelinjen:

Button2->Klikk += gcnew System::EventHandler(this, &Form1::button2_Click);

Før metoden form2->ShowDialog() eller form2->Show() kalles;

I dette tilfellet er behandlerkoden plassert i gjeldende modul Form1.h:

Privat: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) ( MessageBox::Show("Here"); )

Ring et annet skjema fra hovedskjemaet

I menyen velger du Prosjekt - Legg til nytt element- Skjema - navn Skjema2

La oss legge til en operatør

#include "Form2.h"

før det første navneområdet i Form1.h (det vil si helt i begynnelsen av filen).

La oss inkludere en peker til klasseforekomsten i den offentlige delen av Form1-klassen:

Form2^F2;

La oss legge til koden der vi må opprette og kalle det andre skjemaet:

F2=gcnewForm2(); F2->Vis();

For å slette det andre skjemaet programmatisk, er følgende kode egnet:

Slett F2;

Det skal bemerkes at pekeren lagrer adressen til bare ett skjema, det som ble opprettet sist. Hvis vi oppretter flere skjemaer sekvensielt ved hjelp av denne koden, vil bare det siste slettes. Alternativt kan du prøve formmatrisen beskrevet nedenfor.

La oss beskrive de nødvendige dataene i skjemaklassen Form1 (her navnet og navneområdet til Tabulator-prosjektet, om nødvendig, erstatt med ditt eget):

Statisk konstant int MAX_FORMS = 100; //Maksimalt antall skjemaer int FormCount; //Form teller array ^F2; //Pek til en rekke skjemaer

Deretter initialiserer vi dataene ved å bruke Load-hendelsen i hovedskjemaet:

FormCount=0; F2 = gcnew array (MAX_FORMS);

Deretter implementerer vi koden for å lage neste skjema

If(FormCount Forestilling(); ) else MessageBox::Show("For mange skjemaer!");

og fjerning av det:

If (FormCount) ( slett F2; FormCount--; )

Hvis vi ikke vil lage underordnede skjemaer separat, men inne i det overordnede skjemaet, må vi i egenskapene til Form1 indikere at det er en "forfedre" (sett IsMdiParent-egenskapen = true), og før vi viser underordnet form ved å bruke F2->Show()-operator, merk den som underordnet Form1:

F2->MdiParent = dette;

Kalle en overordnet skjemametode fra et underordnet skjema

Vi klarer oss nesten ikke uten å bruke .cpp-filer, noe som ikke er dårlig - å skrive kode i .h-filer bryter generelt det riktige C-systemet :)

La oss beskrive prosessen trinn for trinn.

1) Det er 2 skjemaer - Form1 og Form2, på Form1 er det en Knapp (knapp1, åpner det andre skjemaet) og Etikett (etikett1, her vil vi endre teksten). På Skjema2 - knapp1, når du klikker, vil teksten i label1 endres.

2) Siden vi må ha tilgang til den andre fra den første formen, og fra den andre til den første, vil problemet med kryssreferanser oppstå (når Form1.h refererer til Form2.h, som igjen refererer til til Form1.h) . For å unngå dette vil vi flytte koden til det første skjemaet (Form1), som vil ha tilgang til det andre skjemaet (Form2), fra .h-filen til .cpp-filen. Dermed må du opprette en fil Form1.cpp.

3) Erklær en offentlig sett-metode i Form1.h slik at du kan endre teksten til label1 (koden kan skrives på slutten av filen, etter #pragma endregion):

Offentlig: void Set(String^ text) ( label1->Text = text; )

4) I Form2.h-filen inkluderer vi Form1.h (i begynnelsen):

#include "Form1.h"

og lag en konstruktør som godtar og lagrer en kobling til det første skjemaet for videre bruk:

Form2(Form1^ parent) ( InitializeComponent(); parentForm = parent; ) //du kan skrive en lenke rett under: privat: Form1^ parentForm;

5) Når vi klikker på knappen i Form2, vil vi kalle Set-metoden for det overordnede skjemaet:

Privat: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) ( parentForm->Set("hei fra form2"); parentForm->Show(); this->Hide(); )

6) Det gjenstår å åpne det andre skjemaet i det første skjemaet. For å gjøre dette, flytter vi knappen klikk-behandler fra Form1.h til Form1.cpp , og i .h-filen lar vi bare dens erklæring stå.

Noen ganger er det nødvendig å få tilgang til elementene i ett skjema fra et annet under programkjøring. For eksempel er det et skjema Form1, fra det åpner vi et annet Form2, og nå, når vi jobber i Form2, må vi få tilgang til elementene i det overordnede skjemaet Form1. Jeg fant flere måter å gjøre dette på.

1. metode. Sende en referanse til en offentlig variabel.

Navneområde WindowsApplication1 ( offentlig delklasse Form1: Form ( offentlig Form1() ( InitializeComponent(); ) privat void button1_Click(objektavsender, EventArgs e) ( Form2 frm = new Form2(); frm.but1 = this.button1; // send lenke til knappen i skjemaet Form2 frm.ShowDialog(); ) ) )

I Form2 vil variabelen som koblingen ble sendt til nå tilsvare knapp1 fra Form1

Navneområde WindowsApplication1 ( offentlig delklasse Form2: Form ( public Button but1; // denne variabelen vil inneholde en lenke til button1 fra Form1 public Form2() ( InitializeComponent(); ) privat void button1_Click(objektavsender, EventArgs e) ( but1. Text = "test"; // endre teksten på knappen knapp1 i Form1 ) ) )

2. metode. Sender lenken til barneskjemaet.

Essensen er omtrent den samme i den første metoden. Når vi åpner Form2, sender vi inn en lenke til elementet som vi planlegger å endre senere.

Navneområde WindowsApplication1 ( offentlig delklasse Form1: Form ( public Form1() ( InitializeComponent(); ) privat void button1_Click(objektavsender, EventArgs e) ( Form2 frm = new Form2(this.button1); // send en lenke til knappen til skjemaet Form2 frm.ShowDialog(); ) ) )

Nå i Form2 må vi lage en variabel som vil inneholde en lenke til denne knappen og gjennom den får vi tilgang til knappen på Form1 (linje 5,7,9 og 15).

Navneområde WindowsApplication1 ( offentlig delklasse Form2: Form ( private Button but1; // denne variabelen vil inneholde en lenke til knappen button1 fra skjemaet Form1 public Form2(Button but) // få en lenke til knappen i variabelen but ( but1 = men; // nå vil but1 være en lenke til knapp button1 InitializeComponent(); ) privat void button1_Click(objektavsender, EventArgs e) ( but1.Text = "test"; // endre teksten på knapp knapp1 i Form1 ) ) )

3. metode. Tilgang til hele foreldreskjemaet.

For å gjøre dette må du gjøre endringer i flere filer, men samtidig vil vi ha tilgang til alle elementene i det overordnede skjemaet og trenger ikke sende en lenke til hvert element, som i metode 1.

Trinn 1. I fil Program.cs lag en offentlig variabel f1 (linje 5).

Navneområde WindowsApplication1 ( statisk klasse Program ( offentlig statisk Form1 f1; // variabel som vil inneholde en lenke til skjemaet Form1 static void Main() ( Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1( ) ) ) ) )

Steg 2.Åpning Form1.Designer.cs og i den, for elementer som må åpnes fra et annet skjema, endrer vi privatoffentlig. La oss for eksempel gjøre knapp1 på skjema1 tilgjengelig for endringer.

Offentlig system.Windows.Forms.Button button1; // erstattet privat med offentlig

Trinn 3. Når vi oppretter Form1, tildeler vi variabel f1 en lenke til dette skjemaet (linje 7)

Navneområde WindowsApplication1 ( offentlig delklasse Form1: Form ( public Form1() ( Program.f1 = dette; // nå vil f1 være en lenke til skjemaet Form1 InitializeComponent(); ) privat void button1_Click(objektavsender, EventArgs e) ( Form2 frm = new Form2(); frm.ShowDialog(); ) ) )

Trinn 4. Nå fra absolutt hvilken som helst form eller fra hvilken som helst klasse kan du få tilgang til button1-elementet som ligger på Form1 slik: Program.f1.button1. La for eksempel knappen på Form2 endre knappeteksten på Form1:

Navneområde WindowsApplication1 ( offentlig delklasse Form2: Form ( public Form2() ( InitializeComponent(); ) privat void button1_Click(objektsender, EventArgs e) ( Program.f1.button1.Text = "test"; // Endre teksten på skjemaknapp Skjema1)))

Av admin.

Å lære C# går sakte. men det fortsetter trofast. Nylig jeg
ga et eksempel på hvordan du åpner et annet fra ett skjema i Visual C#. I prinsippet er alt enkelt.

I dag dukket følgende oppgave opp: start et modalt skjema fra hovedskjemaet til applikasjonen; når det er lukket, må dette skjemaet sende noen data (tekst, egenskapsverdier, etc.) til kontrollene på hovedskjemaet. Det er ikke mulig å løse dette problemet ved å bruke metoden beskrevet i forrige innlegg om skjemaer, fordi i dette tilfellet oppretter vi ganske enkelt et nytt skjemaobjekt med nye verdier for alle egenskaper. Heldigvis har C# en fantastisk søppelsamler... Men poenget er ikke samleren, men hvordan åpner man et underordnet skjema i C#, for så å komme tilbake til hovedskjemaet fra det?

Til å begynne med, la oss angi de første (initielle) dataene.

Så. Vi har hovedsøknadsskjemaet:

Dette skjemaet inneholder også en tekstboks med navnet TBDialog og en knapp som vi skal klikke på:

  1. Bestått verdi Tekstegenskaper fra TBDialog til TBMain;
  2. Lukk fDialog;

La oss nå se på hele prosessen i rekkefølge.

For det første er det alltid verdt å huske at som standard er alle egenskaper, variabler og metoder i C# tildelt en modifikator privat– derfor, for å komme fra det andre skjemaet til kontrollen på det første, må vi sette en modifikator for TBMain offentlig på egenhånd. For å gjøre dette, velg TBMain-elementet i skjemadesigneren, gå til egenskapsvinduet og endre eiendomsverdien Modifikatorer Med privatoffentlig

Nå vil TBMain være synlig i andre objekter. La oss gå videre. For å åpne skjemaet i modal modus, må vi bruke ett av to alternativer for ShowDialog()-metoden:

offentlig DialogResult ShowDialog() ; offentlig DialogResult ShowDialog(IWin32Window-eier) ;

I det første tilfellet viser metoden skjemaet som en modal dialogboks med det gjeldende aktive vinduet satt som eier, og i det andre kan vi uavhengig spesifisere hvilket skjema som skal bli eier for vårt modale vindu.

La oss for eksempel bruke den andre versjonen av metoden ShowDialog() og vise den andre formen modalt. For å gjøre dette, vil vi skrive følgende:

Her utnyttet jeg igjen nøkkelord dette , som peker på det aktuelle objektet, dvs. angi hovedskjemaet som eier ( fMain). La oss nå gå direkte til å løse problemet vårt og svare på spørsmålet: hvordan overføre verdi fra en form til en annen? Hver kontroll har en bemerkelsesverdig egenskap Eieren – som peker på forelderen:

Nå kan du kjøre prosjektet og sørge for at teksten fra tekstboksen på underordnet skjema overføres perfekt til tekstboksen på den første. Bare i tilfelle legger jeg ut kildekoden til prosjektet diskutert i eksemplet.