[HowTo] ¿Como pasar datos entre dos Windows Forms?

En los foros de C#, ésta es una pregunta habitual, y no es para menos, si apenas comienzas con el lenguaje tareas como esta se dificultan, es por eso que me he decidido a hacer este post, para mostrar las soluciones que he encontrado a tan habitual problema, describiendo sus pros y sus contras en qué casos sí y en qué casos no es bueno aplicarlas.

El escenario es: ¿Cómo pasar los datos de una variable que está en un Form a otro? Para el desarrollo de los ejemplos he agregado dos Windows Forms a una aplicación Windows Forms en C#, en el Form1 he agregado un botón (button1) y el Form2 sin ningún control.

La primera de las soluciones que empleé, fue declarar variables públicas en el form que recibe los datos (a partir de ahora Form2) y alterar su valor desde la instancia del form que envía la información (a partir de ahora Form1). En la clase del Form2, tengo una variable pública que recibe la info del form1 y en su evento Load público un MessageBox con la variable:

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

        public string recibir_datos; //variable del tipo de dato que necesites pasar, en el caso del ejemplo sera string
        private void Form2_Load(object sender, EventArgs e)
        {
            MessageBox.Show(recibir_datos); //Mostrar valor de la variable
        }
}

Si lo ejecutas, al dar clic en el botón del Form1 te mostrará un MessageBox con el valor de la variable que pasamos, “lo logramos”. Peroooo… el que funcione no quiere decir que sea lo mejor ¿Por qué?, pues porqué en este caso simplemente pasamos un string sin sentido, pero recuerda que la variable ES PÚBLICA, es decir, esta propiedad es visible para cualquier clase que acuda a ésta (Form2), lo que nos genera problemas de seguridad.
Teniendo claro esto, pensé en una segunda opción, en la que la propiedad no quedara visible a las otras clases.
En el Form2 “pido” como parámetro al variable en el método de la clase (public Form2()) y se lo asigno a una variable privada dentro de esta clase, así:

private string recibir_datos; //Declaracion de la variable con modificador de acceso PRIVADO 

public Form2(string el_parametro) // se solicita un parametro del tipo string en el metodo de la Clase 
{
            InitializeComponent();
            recibir_datos = el_parametro; //se asigna el valor del parametro a la variable privada.
}

private void Form2_Load(object sender, EventArgs e)
{
            MessageBox.Show(recibir_datos); //Se muestra el valor de la variable privada
}

¡Funciona! y  es seguro, a decir verdad, es una solución simple y elegante, pues ocultamos el valor de la propiedad de las demás clases que pudiesen acceder a este. Perooo, a esta le he encontrado un problema, y es que este parámetro es obligatorio, es decir, siempre se va a pedir este valor en el constructor ¿Y si no queremos pasar ningún valor desde el Form3 (p. ej)? Sería poco elegante de nuestra parte pasar datos al azar, o que no tengan nada que ver. Por fortuna para nosotros C# soporta SOBRECARGA, en realidad todos los lenguajes orientados a objetos lo hacen, esto nos da la posibilidad de tener  dos métodos con el mismo nombre pero con distinta cantidad de argumentos, es decir, podemos o no, pasar el dato a el constructor. Para esto alteramos nuestro Form2 levemente:

private string recibir_datos;
 public Form2() //Metodo de la clase sin parametros
 {
 InitializeComponent();
 }
 public Form2(string el_parametro) //Metodo de la clase que espera un parametro
 {
 InitializeComponent();
 recibir_datos = el_parametro;
 }
 private void Form2_Load(object sender, EventArgs e)
 {
 if(!string.IsNullOrEmpty(recibir_datos))  //Por cuestiones de elegancia, si la variable esta vacia NO MUESTRA MENSAJE
 MessageBox.Show(recibir_datos);
 }

En el Form1 he agregado otro botón (button2) en el que no se pasará parámetro en el constructor, así:

private void button1_Click(object sender, EventArgs e)
{
            string variable = "Texto enviado de un form a otro"; 
            Form2 frm2 = new Form2(variable); //Pasando Variable en el constructor            
            frm2.Show();            
}
private void button2_Click(object sender, EventArgs e)
{
            Form2 frm2 = new Form2(); //sin variable en el constructor
            frm2.Show();            
}

Ésta es mucho mas elegante y segura, no le he encontrado ningún problema, pero si una limitación, la sobrecarga solo nos admite métodos con distinto tipo de argumentos, es decir, no podemos tener dos métodos con el mismo nombre, la misma cantidad de parámetros y del mismo tipo. Para esta limitación, la solución es muy simple, nos creamos un método propio en el Form2 que le de el valor a la variable y listo. El código queda así:

private string recibir_datos;

public void setearvariable(string el_otro_parametro) //Método del tipo void (no retorna valor)
{
            recibir_datos = el_otro_parametro; //asignar variable privada lo que tenga el parámetro
}
private void Form2_Load(object sender, EventArgs e)
{
            if(!string.IsNullOrEmpty(recibir_datos))
                MessageBox.Show(recibir_datos);  //Publica datos si esta no viene vacía          
}

Espero les sea de utilidad.

Descarga el ejemplo

Hasta el próximo post.

Anuncios
[HowTo] ¿Como pasar datos entre dos Windows Forms?

5 comentarios en “[HowTo] ¿Como pasar datos entre dos Windows Forms?

  1. La solucion correcta a este problema es muy sencilla: NO tener variables en los formularios.

    Si se usa un patron para disenar interfaces como MVC (Modelo-Vista-Controlador), el formulario es la Vista (y seguramente el Controlador tambien usando sus eventos), pero el Modelo, que son los datos, es una clase a parte.

    Organizado asi, los formularios utilizan sus eventos para modificar los datos en el Modelo, y al mismo tiempo, leen los campos que necesiten del modelo para mostrarlos. Por ejemplo, podrias tener un modelo que representa el numero de ventas de varios productos de una empresa, y en un formulario mostrar esos datos en un grid y en otro formulario en una grafica de barras.

    La explicacion de la Wikipedia:

    http://es.wikipedia.org/wiki/Modelo_vista_controlador

    Aunque hay muchisimos articulos del tema por internet, y luego variantes como MVP y MVVM (que es el que se utiliza en WPF).

  2. Hola Vicente, totalmente de acuerdo con tigo. . . decidi “mezclar” las capas para no extenderme en este post, creo qe voy crear una categoria “Las Mejores practicas en C#” o algo así donde presente cosillas un tanto mas “avanzadas” para usuarios con un tantico mas de experiencia, gracias por leer el post y opinar al repecto, Un abrazo.

  3. Anónimo dijo:

    muy buena solucion, tengo una pregunta, tengo form1 y form2 en el form1 tengo una caja de texto y a lado un boton que me lleva a form2 este form contiene un gridview este gris solo contiene una columna y la quiero pasar a el form2 dentro de la caja de texto

    podrian ayudarme

  4. sebastian dijo:

    Hola, muy buen post..me soluciono algunos problemas que no entendia..
    te cuento este a ver si se te ocurre alguna idea..
    yo tengo 2 formularios..y del 1º formulario(form1) toco un boton para llamar al otro formulario (form2)..en este formulario tengo un listview con checkbox y los elementos que elijo, los guardo en una variable y los quiero mandar a otra variable en el form1 (osea volver al formulario anterior con los datos que obtuve del form2)..pero al cerrar el form2 se pierden los datos (tienen valor null) y nose me ocurre como solucionarlo..
    desde ya gracias..y cualquier ayuda es bienvenida 🙂

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s