Comuníquese entre dos formularios de Windows en C #

Tengo dos formularios, uno es el formulario principal y el otro es un formulario de opciones. Por ejemplo, supongamos que el usuario hace clic en mi menú en el formulario principal: Tools -> Options , esto haría que se mostrara mi formulario de opciones.

Mi pregunta es ¿cómo puedo enviar los datos de mi formulario de opciones a mi formulario principal? Sé que podría usar propiedades, pero tengo muchas opciones y esto parece una cosa tediosa y extraña.

Entonces, ¿cuál es la mejor manera?

Form1 activa Form2 para abrir. Form2 ha sobrecargado el constructor que toma la forma de llamada como argumento y proporciona su referencia a los miembros de Form2. Esto resuelve el problema de comunicación. Por ejemplo, he expuesto Label Property como público en Form1, que se modifica en Form2.

Con este enfoque, puedes hacer comunicación de diferentes maneras.

Enlace de descarga para el proyecto de ejemplo

// Su 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; } } } 

// Su 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; } } 

texto alternativo http://demo.ruchitsurati.net/files/frm1.png

texto alternativo http://demo.ruchitsurati.net/files/frm2.png

En los comentarios a la respuesta aceptada, Neeraj Gulia escribe:

Esto conduce a un acoplamiento estrecho de los formularios Form1 y Form2, supongo que uno debería usar eventos personalizados para ese tipo de escenarios.

El comentario es exactamente correcto. La respuesta aceptada no está mal; para progtwigs simples, y especialmente para personas que recién están aprendiendo progtwigción e intentando que funcionen escenarios básicos, es un ejemplo muy útil de cómo un par de formularios puede interactuar.

Sin embargo, es cierto que el acoplamiento que causa el ejemplo puede y debe evitarse, y que en el ejemplo particular, un evento lograría lo mismo en una forma desacoplada de propósito general.

Aquí hay un ejemplo, usando el código de la respuesta aceptada como línea de base:

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(); } } 

El código anterior crea una nueva instancia de Form2 y luego, antes de mostrarlo, agrega un controlador de eventos al evento Button1Click ese formulario.

Tenga en cuenta que la expresión (sender, e) => Lbl.Text = ((Form2)sender).Message se convierte automáticamente por el comstackdor a un método que se ve algo similar a (pero definitivamente no exactamente como) esto:

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

En realidad, hay muchas formas / syntax para implementar y suscribir el controlador de eventos. Por ejemplo, usando un método anónimo como el anterior, realmente no necesita convertir el parámetro del sender ; en su lugar, puede usar directamente la variable local frm : (sender, e) => Lbl.Text = frm.Message .

Yendo para otro lado, no necesitas usar un método anónimo. De hecho, puede declarar un método regular como el generado por el comstackdor que muestro arriba, y luego suscribir ese método al evento: frm.Button1Click += frm_Message; (donde, por supuesto, frm_Message el nombre frm_Message para el método, al igual que en mi ejemplo anterior).

Independientemente de cómo lo haga, por supuesto necesitará Form2 para implementar realmente ese evento Button1Click . Eso es muy simple …

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); } } } 

Además del evento, también he declarado un Message propiedad que expone la propiedad Text (y solo la propiedad Text , y solo como de solo lectura de hecho) del control txtMessage . Esto permite que el suscriptor del evento obtenga el valor y haga lo que necesite con él.

Tenga en cuenta que todo lo que hace el evento es alertar al suscriptor de que se ha hecho clic en el botón. Depende del suscriptor decidir cómo interpretar o reactjsr a ese evento (por ejemplo, recuperando el valor de la propiedad del Message y asignándolo a algo).

Alternativamente, de hecho podría entregar el texto junto con el evento mismo, declarando una nueva subclase EventArgs y usándola para el evento en su lugar:

 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)); } } } 

Luego, el suscriptor puede recuperar el valor del mensaje directamente desde el objeto del evento:

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

La nota importante en todas las variaciones anteriores es que en ningún momento la clase Form2 necesita saber nada sobre Form1 . Tener Form1 sabe acerca de Form2 es inevitable; después de todo, ese es el objeto que creará una nueva instancia de Form2 y la usará. Pero la relación puede ser asimétrica, y Form2 puede ser utilizada por cualquier objeto que necesite las características que ofrece. Al exponer la funcionalidad como un evento (y opcionalmente con una propiedad), se vuelve útil sin limitar su utilidad solo a la clase Form1 .

Lo mejor en este caso sería tener alguna clase / interfaz de IServiceProvider accesible a través de IServiceProvider .

Simplemente agregue un evento cuando algo cambie y el rest de la aplicación pueda responder.

Propiedades es una opción, clase estática compartida – otra opción, eventos – otra opción …

Puede probar AutoMapper . Mantenga sus opciones en una clase separada y luego use AutoMapper para transferir los datos entre la clase y el formulario.

Cree una clase y coloque todas sus propiedades dentro de la clase. Cree una propiedad en la clase principal y configúrela desde su formulario secundario (opciones)

Puede tener una función en la Forma B como esta:

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

Y puedes llamarlo así:

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

MVC, MVP, MVVM: una pequeña exageración para alguien que admite que quiere tutoriales. Esas son teorías que tienen cursos enteros dedicados a ellos.

Como ya se ha publicado, es más fácil pasar un objeto. Si el tratamiento de una clase como un objeto (intercambiable en este sentido) es nuevo, entonces es posible que desee pasar otras 2-4 semanas averiguando propiedades y constructores, etc.

No soy un maestro de C # de ninguna manera, pero estos conceptos deben ser bastante concretos si quieres ir mucho más allá de pasar valores entre dos formularios (también clases / objetos por derecho propio). No tratando de ser malo aquí en absoluto, suena como si estuvieras pasando de algo como VB6 (o cualquier lenguaje con globales) a algo mucho más estructurado.

Eventualmente, hará clic.

Probablemente este sea eludir un poco su problema, pero mi cuadro de diálogo de configuración usa la construcción de Configuración de la aplicación. http://msdn.microsoft.com/en-us/library/k4s6c3a0.aspx

No puedo encontrar un buen ejemplo que sea similar a cómo lo hago (que en realidad tiene un objeto clase + real), pero esto cubre otra forma de hacerlo:

Leer la configuración de la aplicación predeterminada en C #

Un formulario es una clase, como cualquier otra clase. Agregue algunas variables públicas a su clase de formulario y configúrelas cuando hagan clic en el botón para cerrar el formulario (técnicamente solo lo están ocultando).

Un ejemplo de VB.NET, pero obtendrás la idea:

En tu clase de OptionsForm:

 Public Option1 as String = "" 

etc. Configúrelos cuando presione el botón “Aceptar”.

Entonces, en su forma principal, cuando presionan el botón de “opciones”, crea su formulario de opciones:

 OptionsForm.ShowDialog() 

cuando sale, cosecha la configuración de sus opciones de las variables públicas en el formulario:

 option1 = OptionsForm.Option1 

etc.

Hay muchas maneras de realizar la comunicación entre dos formularios. Algunos de ellos ya han sido explicados. Te estoy mostrando al revés.

Suponiendo que tiene que actualizar algunas configuraciones desde el formulario secundario al formulario principal. Puede hacer uso de estas dos formas también:

  1. Usando System.Action (Aquí simplemente pasas la función de formularios principales como el parámetro al formulario hijo como una función de callback)
  2. Método OpenForms (Usted llama directamente a uno de sus formularios abiertos)

Usando System.Action

Puede pensarlo como una función de callback pasada al formulario secundario.

 // -------- 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"); } 

Método OpenForms

Este método es fácil ( 2 líneas ). Pero solo funciona con formularios que están abiertos. Todo lo que necesita hacer es agregar estas dos líneas donde quiera que quiera pasar algunos datos.

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