Comunica tra due moduli Windows in C #

Ho due forms, una è la forma principale e l’altra è una forma di opzioni. Ad esempio, per esempio, l’utente fa clic sul mio menu nel modulo principale: Tools -> Options , questo causerebbe la visualizzazione del modulo delle opzioni.

La mia domanda è come posso inviare i dati dal mio modulo di opzioni al mio modulo principale? So che potrei usare le proprietà, ma ho un sacco di opzioni e questa sembra una cosa strana noiosa da fare.

Allora, qual è il modo migliore?

Form1 triggers Form2 per aprire. Form2 ha sovraccaricato il costruttore che prende la forma chiamante come argomento e fornisce il suo riferimento ai membri di Form2. Questo risolve il problema di comunicazione. Ad esempio, ho esposto la proprietà Label come pubblica in Form1 che viene modificata in Form2.

Con questo approccio puoi fare comunicazione in diversi modi.

Scarica il link per il progetto di esempio

// Il tuo Form1

 public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Form2 frm = new Form2(this); frm.Show(); } public string LabelText { get { return Lbl.Text; } set { Lbl.Text = value; } } } 

// Il tuo Form2

 public partial class Form2 : Form { public Form2() { InitializeComponent(); } private Form1 mainForm = null; public Form2(Form callingForm) { mainForm = callingForm as Form1; InitializeComponent(); } private void Form2_Load(object sender, EventArgs e) { } private void button1_Click(object sender, EventArgs e) { this.mainForm.LabelText = txtMessage.Text; } } 

alt text http://demo.ruchitsurati.net/files/frm1.png

alt text http://demo.ruchitsurati.net/files/frm2.png

Nei commenti alla risposta accettata, Neeraj Gulia scrive:

Ciò porta ad un accoppiamento stretto dei moduli Form1 e Form2, suppongo invece che si dovrebbero usare eventi personalizzati per questo tipo di scenari.

Il commento è esattamente giusto. La risposta accettata non è male; per i programmi semplici, e specialmente per le persone che apprendono semplicemente la programmazione e cercano di far funzionare gli scenari di base, è un esempio molto utile di come una coppia di forms può interagire.

Tuttavia, è vero che l’accoppiamento che causa l’esempio può e deve essere evitato, e che nell’esempio particolare, un evento realizzerebbe la stessa cosa in un modo generale, disaccoppiato.

Ecco un esempio, utilizzando come riferimento il codice della risposta accettata:

Form1.cs:

 public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Form2 frm = new Form2(); frm.Button1Click += (sender, e) => Lbl.Text = ((Form2)sender).Message; frm.Show(); } } 

Il codice precedente crea una nuova istanza di Form2 e quindi prima di mostrarlo aggiunge un gestore di eventi all’evento Button1Click di tale modulo.

Si noti che l’espressione (sender, e) => Lbl.Text = ((Form2)sender).Message viene convertita automaticamente dal compilatore in un metodo che sembra qualcosa di simile a (ma sicuramente non esattamente come) questo:

 private void frm_Message(object sender, EventArgs e) { Lbl.Text = ((Form2)sender).Message; } 

Esistono molti modi / syntax per implementare e sottoscrivere il gestore di eventi. Ad esempio, utilizzando un metodo anonimo come sopra, non è davvero necessario eseguire il cast del parametro del sender ; puoi invece usare direttamente la variabile locale frm : (sender, e) => Lbl.Text = frm.Message .

Andando dall’altra parte, non è necessario utilizzare un metodo anonimo. In effetti, puoi semplicemente dichiarare un metodo regolare proprio come quello generato dal compilatore che mostro sopra, e quindi iscrivere quel metodo all’evento: frm.Button1Click += frm_Message; (dove ovviamente hai usato il nome frm_Message per il metodo, proprio come nel mio esempio sopra).

Indipendentemente da come lo fai, ovviamente è necessario che Form2 effettivamente l’evento Button1Click . È molto semplice …

Form2.cs:

 public partial class Form2 : Form { public event EventHandler Button1Click; public string Message { get { return txtMessage.Text; } } public Form2() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { EventHandler handler = Button1Click; if (handler != null) { handler(this, EventArgs.Empty); } } } 

Oltre all’evento, ho anche dichiarato un Message proprietà che espone la proprietà Text (e solo la proprietà Text e solo in sola lettura di fatto) del controllo txtMessage . Ciò consente all’abbonato dell’evento di ottenere il valore e fare tutto ciò che è necessario con esso.

Si noti che tutto ciò che fa l’evento è di avvisare il sottoscrittore che il pulsante è stato effettivamente cliccato. Spetta all’abbonato decidere come interpretare o reactjs a quell’evento (ad es. Recuperando il valore della proprietà Message e assegnandolo a qualcosa).

In alternativa, puoi effettivamente consegnare il testo insieme all’evento stesso, dichiarando una nuova sottoclass EventArgs e utilizzandola invece per l’evento:

 public class MessageEventArgs : EventArgs { public string Message { get; private set; } public MessageEventArgs(string message) { Message = message; } } public partial class Form2 : Form { public event EventHandler Button1Click; public Form2() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { EventHandler handler = Button1Click; if (handler != null) { handler(this, new MessageEventArgs(txtMessage.Text)); } } } 

Quindi l’abbonato può semplicemente recuperare il valore del messaggio direttamente dall’object evento:

 frm.Button1Click += (sender, e) => e.Message; 

La nota importante in tutte le varianti sopra riportate è che la class Form2 non ha mai bisogno di sapere nulla su Form1 . Avere Form1 conoscenza di Form2 è inevitabile; dopo tutto, questo è l’object che creerà una nuova istanza di Form2 e la userà. Ma la relazione può essere asimmetrica, con Form2 è utilizzabile da qualsiasi object che abbia bisogno delle caratteristiche che offre. Esponendo la funzionalità come un evento (e facoltativamente con una proprietà), si rende utile senza limitare la sua utilità solo alla class Form1 .

In questo caso, il migliore sarebbe disporre di una class / interfaccia IServiceProvider accessibile tramite IServiceProvider .

Aggiungi un evento quando qualcosa cambia e il resto dell’app può rispondere.

Proprietà è un’opzione, class statica condivisa – un’altra opzione, eventi – un’altra opzione …

Potresti provare AutoMapper . Mantieni le tue opzioni in una class separata e poi usa AutoMapper per spostare i dati tra la class e il modulo.

Crea una class e metti tutte le tue proprietà all’interno della class. Crea una proprietà nella class genitore e impostala dal tuo modulo figlio (opzioni)

Puoi avere una funzione in Form B in questo modo:

 public SettingsResults GetNewSettings() { if(this.ShowDialog() == DialogResult.Ok) { return new SettingsResult { ... }; } else { return null; } } 

E puoi chiamarlo così:

 ... using(var fb = new FormB()) { var s = fb.GetNewSettings(); ... // Notify other parts of the application that settings have changed. } 

MVC, MVP, MVVM – lieve esagerazione per qualcuno che ammette di voler tutorial. Quelle sono teorie che hanno interi corsi a loro dedicati.

Come già pubblicato, passare un object è probabilmente il più facile. Se il trattamento di una class come object (intercambiabile in questo senso) è nuovo, allora potresti voler dedicare altre 2-4 settimane a capire proprietà e costruttori e così via.

Non sono un maestro di C # in alcun modo, ma questi concetti devono essere abbastanza concreti se si vuole andare oltre il passaggio di valori tra due forms (anche classi / oggetti a sé stanti). Non cercare di essere meschino qui, sembra solo che tu ti stia spostando da qualcosa come VB6 (o qualsiasi altra lingua con i globals) a qualcosa di molto più strutturato.

Alla fine, farà clic.

Questo probabilmente aggira un po ‘il problema, ma la mia finestra di dialogo delle impostazioni usa il costrutto Impostazioni applicazione. http://msdn.microsoft.com/en-us/library/k4s6c3a0.aspx

Non riesco a trovare un buon esempio simile al modo in cui lo faccio (che in realtà è un effettivo object di class +), ma questo copre un altro modo di farlo:

Lettura delle impostazioni predefinite dell’applicazione in C #

Una forma è una class, proprio come qualsiasi altra class. Aggiungi alcune variabili pubbliche alla class del form e impostale quando fanno clic sul pulsante per chiudere il modulo (tecnicamente lo stanno solo nascondendo).

Un esempio VB.NET, ma ti verrà l’idea –

Nella tua class OptionsForm:

 Public Option1 as String = "" 

ecc. Impostali quando colpiscono il pulsante “Ok”.

Quindi nella tua forma principale, quando colpiscono il pulsante “opzioni” – crei il modulo delle opzioni:

 OptionsForm.ShowDialog() 

quando esce, raccogli le impostazioni delle opzioni dalle variabili pubbliche nel modulo:

 option1 = OptionsForm.Option1 

eccetera.

Esistono molti modi per eseguire comunicazioni tra due moduli. Alcuni di loro sono già stati spiegati. Ti sto mostrando il contrario.

Supponendo di dover aggiornare alcune impostazioni dal modulo figlio al modulo padre. Puoi utilizzare anche questi due modi:

  1. Utilizzo di System.Action (Qui si passa semplicemente la funzione form principale come parametro alla forma figlio come una funzione di callback)
  2. Metodo OpenForms (chiama direttamente uno dei tuoi moduli aperti)

Utilizzando System.Action

Si può pensare ad esso come una funzione di callback passata al modulo figlio.

 // -------- IN THE MAIN FORM -------- // CALLING THE CHILD FORM IN YOUR CODE LOOKS LIKE THIS Options frmOptions = new Options(UpdateSettings); frmOptions.Show(); // YOUR FUNCTION IN THE MAIN FORM TO BE EXECUTED public void UpdateSettings(string data) { // DO YOUR STUFF HERE } // -------- IN THE CHILD FORM -------- Action UpdateSettings = null; // IN THE CHILD FORMS CONSTRUCTOR public Options(Action UpdateSettings) { InitializeComponent(); this.UpdateSettings = UpdateSettings; } private void btnUpdate_Click(object sender, EventArgs e) { // CALLING THE CALLBACK FUNCTION if (UpdateSettings != null) UpdateSettings("some data"); } 

Metodo OpenForms

Questo metodo è facile ( 2 linee ). Ma funziona solo con le forms che sono aperte. Tutto quello che devi fare è aggiungere queste due righe dove vuoi passare alcuni dati.

 Main frmMain = (Main)Application.OpenForms["Main"]; frmMain.UpdateSettings("Some data");