En esta entrega de HazloExpress cubriremos la necesidad de pasar datos entre formularios en C# con Windows Form o WinForm.
Por lo general pasamos datos desde un formulario a otro formulario al momento de llamarlo y lo hacemos haciendo uso del constructor de la clase de ese formulario o a través de algún método público que contenga.
¿Pero que pasa si queremos pasar datos desde un formulario ya abierto hacia el formulario que lo invocó?
Si estas leyendo este post, entonces es porque te habrás dado cuenta de que pareciera ser imposible. Y te puedo decir que, aunque parezca difícil o imposible, ¡no lo es!
Si Bien podrías usar variables estáticas y pasar la data, pero que pasa si tienes varias ventanas que necesitan esta operación, además de que es un derroche de recurso usar variables estáticas para estos fines.
Bien, ¿entonces cual es la forma correcta?
¡Interfaces!
Sí, con una interfaz podemos solucionar este problema, usando un principio de desarrollo orientado a objeto llamado inversión de dependencia.
Para esto crearemos un proyecto en visual studio y seleccionaremos como lenguaje de programacion a C# le llamaremos ComunicarFormularios.
En nuestro proyecto usaremos 2 formularios
Uno será llamado padre (Este será el que invoca, el que recibirá los datos)
El otro será llamado hijo (quien envía los datos)
También necesitaremos una Interface.
Esta será llamada IContract y solo contendrá un método llamado Ejecutar, (ojo, la interfaz se crean sin modificador de acceso, para este ejemplo se le aplicara el modificador de acceso public).
namespace ComunicarFormularios { public interface IContract { void Ejecutar(string texto); } }
Ahora bien, la ventana o formulario llamado Padre tendrá los siguientes controles
Daremos doble clic en el botón y agregaremos el siguiente código
Hijo hijo = new Hijo(); hijo.contrato = this; hijo.Show();
También heredaremos de la interfaz Icontract e implementaremos su método el cual sobrescribiremos con el código siguiente.
public void Ejecutar(string texto) { LblMensaje.Text = texto; //control label }
La clase padre quedaría de la siguiente forma
namespace ComunicarFormularios { public partial class Padre : Form , IContract { public Padre() { InitializeComponent(); } public void Ejecutar(string texto) { LblMensaje.Text = texto; } private void BtnLlamarHijo_Click(object sender, EventArgs e) { Hijo hijo = new Hijo(); hijo.contrato = this; hijo.Show(); } } }
También puede que te interese Como filtrar datos en Datagridview C#
La ventana Hijo tendrá los siguientes controles
En este formulario iremos a la clase y agregaremos una propiedad de tipo Icontract la cual llamaremos contrato.
public IContract contrato { get; set; }
En el botón enviar mensaje daremos doble clic y agregaremos el siguiente código
private void BtnEnviar_Click(object sender, EventArgs e) { contrato.Ejecutar(TxtMensaje.Text); }
La clase quedaría de la siguiente forma
namespace ComunicarFormularios { public partial class Hijo : Form { public IContract contrato { get; set; } public Hijo() { InitializeComponent(); } private void BtnEnviar_Click(object sender, EventArgs e) { contrato.Ejecutar(TxtMensaje.Text); } } }
Ahora ejecutaremos a la aplicación y obtendremos el siguiente resultado
Eso es todo!
Explicación
El formulario hijo no tiene el mecanismo para hacer referencia hacia el objeto que lo invocó, sin embargo cuando instanciamos el objeto hijo le asignamos a la propiedad contracto el valor this, este le pasa la referencia del objeto que lo está invocando o llamando.
//clase padre Hijo hijo = new Hijo(); hijo.contrato = this; // paso de referencia hijo.Show(); //Clase Hijo public IContract contrato { get; set; }
La interfaz por su parte crea una especie de contrato entre ambos objetos, lo cual le permite al objeto hijo invocar los métodos que contiene la interfaz, pero desde la clase padre, ya que el objeto de tipo interfaz fue inicializado con la referencia de la clase padre.
Despues de todo no era tan dificil pasar datos entre formularios C# en WinForm , lo bueno de esto es que puedes utilizar este mecanismo para pasar datos entre objetos, no solo formularios, y mejor aun puedes utilizarlo en cualquier lenguaje de programacion orientado a objetos.
Espero que te sea de ayuda, dale me gusta y no te olvide de compartir y valorar este post.
no me funciona tu codigo y eso que copie y pegue todo con los mismos nombres y toda la cosa pero me manda un error al crear la propiedad tipo IContract me dice que existe una incoherencia y manda el error CS0053 no se si me podrias ayudar con eso
Hola @TSM_KRIS, este error ‘CS0053’, es producido debido a que cuando creas una **interface**, por defecto se crea sin modificador de acceso.
la solución es que en la interfaz IContract, le coloques el modificador public delante.
public interface IContrac
{
}
hola me sale un error seguí todos los pasos cuidadosa mente
el error que me manda es el CS0535 ayuda !!!
Hola emerson, ese error se debe a que la clase que implementa la interfaz, tambien debe implementar los metodos, en este caso debes reescribir el metodo Ejecutar en la clase Padre
me subraya la palabra contrato y me dice
(codigo de error CS1061)
C # ‘Formulario’ no contiene una definición y no se puede encontrar ningún método de extensión accesible que acepte un primer argumento de tipo ‘Formulario’ (¿falta una directiva de uso o una referencia de ensamblado?))
Hola Luis, tiene que crear una variable en la clase del formulario definido como el hijo, o el que es llamado, donde la variable debe ser del tipo de la interfaz.
Gracias por comentar.
hola, estoy probando tu código pero hablas de un «contrato» y eso en ninguna parte la declaras, tiene que ir en la interface?
en el Código hay dos formularios y una interfaz,
la variable contrato debe ir en la clase que devolverá los valores
Muy bien hecho, de hecho lo necesitaba para java y como son lenguajes muy parecidos lo entendí, muchas gracias man
Gracias Marcos, por comentar, c# y java son idénticos, y todo lo relacionado con orientación a objeto es similar en ambos
Gracias, me sirvió. solo me demoré un poco en descubrir que de que la interface era public.
si, lo que sucede es que visual studio crea las clases e interfaces sin modificador de acceso publico, tenemos que agregarselo nosotros.
ya corregí esa parte en el tuto.
Gracias, me funciono a la perfeccion, aunque la verdad no logro entenderlo del todo. Ahora toca implementarlo en un proyecto que estoy haciendo.
Gracias por comentar.
el funcionamiento esta fundamentado en el paso por valor y paso por referencias, para este caso como es un objeto se aplica lo de paso por referencias.
Esto permite que puedas acceder a una propiedad y/o métodos de un objeto desde otra ubicación del código siempre y cuando sea publico o internal
Si quisiera mandar mas de un comando tengo que agregar mas interfaces??
puedes agregar otro método a la interfaz, pero según el principio de segregación de interfaces es mejor tener una interfaz por metodo.
en tu caso seria una interfaz por comando (metodo).
Gracias, si funciona a la perfeccion.
Perfecto, Me alegra que te sea de ayuda!!
Muy bueno! funciona a la perfección. Muchas gracias.
Genial!!, me alegra que te haya sido util!
Buenas que tal.. estoy probando tu codigo entre 2 formularios, 1 es ventas y el otro es buscar clientes y me sale error en el boton de buscar clientes, dejo el codigo :
private void btnBuscarCli_Click(object sender, EventArgs e)
{
frmBuscarCliente hijo = new frmBuscarCliente();
hijo.contrato = this; // en el this me marca el error: Ya existe una coversion explicita….
hijo.ShowDialog();
Saludos Ruben.
al mirar tu codigo no puedo determinar el error.
pero te puedo sugerir que verifiques 2 cosas:
1 – La clase Venta debe implementar la interfaz IContract
2 – La propiedad que se llama contrato la cual esta en la clase FrmBuscarCliente debe ser de tipo IContract
espero puedas resolver el error y esto te sea de ayuda
hola a mi me da un error que se refiere a que el objeto de la interface esta nulo y no hace nada y bueno últimamente esos errores de referencias nulas me salen mucho
Saludos Luis.
Cuando invocas al formulario Hijo debes tambien pasarle la referencia del padre,
esto se hace cuando le asignas this a la propiedad del tipo de la interfaz en el formulario hijo
Excelente, gracias ,fue de mucha ayuda
Perfecto Abraham, me alegra que te haya sido util
Funciona bien! tuve que prestar atencion en cada linea del codigo al principio porque no funcionaba.
Probado en Visual Studio 2019 c#.
Me habia olvidado colocar Icontract en esta parte:
Padre : Form , IContract
Gracias.
Vaya mierda de tutorial no funciona