Introducción
Este artículo es consecuencia de otros descriptos con anterioridad
C# – Comunicar formularios de forma desacoplada
Como se habrá visto comunicar formularios de forma desacoplada puede no se tan simple alguna veces y es justamente cuando se hace uso de información entre grillas que la situación puede ser algo mas compleja
Este ejemplo intenta demostrar como realizar la comunicación y desde un formulario hijo pasar información de ítems seleccionados al un formulario padre o quien realiza la llamada.
Definición de la Interfaz
Para la comunicación eficiente de los formulario, se crearan un contrato que permitirá enlazarlos con el mínimo acoplamiento entre ellos.
interface IAddItem { void AddNewItem(DataGridViewRow row); }
Como se observa el método que tomara el retorno de la selección del ítem define un DataGridViewRow, o sea un registro completo seleccionado en la grilla del formulario hijo.
Formulario Padre
Como se observara el formulario padre que realizara la apertura debe implementar la interfaz IAddItem definida en el punto anterior.
public partial class Form1 : Form, IAddItem { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Form2 formAdd = new Form2(); formAdd.Show(this); } #region IAddItem Members public void AddNewItem(DataGridViewRow row) { string item = row.Cells["item"].Value.ToString(); string desc = row.Cells["Desc"].Value.ToString(); this.dataGridView1.Rows.Add(new []{ item, desc }); } #endregion }
Es importante destacar algunas líneas:
- Línea 11: es el punto en donde se realiza la apertura del forma hijo, y es allí donde se le indica quien es el padre o quien esta realizando al apertura del formulario, esto se esta indicando al hacer uso del “this” en el parámetro del método Show()
- Líneas 17-24: en estas línea de código se estará tomando la fila que se retorna de la selección, se recupera cada valor y se arma el nuevo registro, en este punto en caso de que fuera necesario se podría realizar cálculos o modificar los datos, para ser luego insertados en la grilla de ítems seleccionados.
Formulario Hijo
Este formulario contiene la grilla con los ítems que pueden ser seleccionados, los cuales a modo de ejemplo fueron creados manualmente en un DataTable.
El punto clave aquí es el botón que envía el registro seleccionado, del datagridview del formulario hijo al formulario padre que realizo la llamada:
private void button1_Click(object sender, EventArgs e) { DataGridViewRow row = this.dataGridView1.SelectedRows[0] as DataGridViewRow; IAddItem parent = this.Owner as IAddItem; parent.AddNewItem(row); this.Close(); }
Como se observa se toma la fila seleccionada, y acto seguido se llamada al método de la interfaz del formulario que realizo la llamada.
El parámetro “this” enviado en el método Show() es justamente la propiedad Owner del formulario hijo, y al implementar la interfaz este puede ser casteado a el tipo IAddItem sin problemas, para luego invocar al método que define.
[C#] |
[VB.NET] |
Hola leandro, disculpa pero esto no tiene nada que ver con la entrada que hicistes, pero me gustaria saber que sitios puedo revisar para mantenerme actualizado y que blogs, ya que muchos blogs dejan de postear, los boletines de la microsoft me llegan siempre pero algo adicional. gracias
ResponderEliminarHola Leandro, soy un poco novato en el c# estuve siguiendo el ejemplo que de pasaje de iformacion y me salta un error en la linea parent.AddNewItem(row); del form hijo, dice "referencia a objeto no establecida como instacia de un objeto" desde ya muchas gracias estan geniales tus aportes
ResponderEliminarhola alemar
ResponderEliminarNo se si habias podido descargar el ejemplo de codigo, ya que tuve problemas con skydrive, pero ahora esta publicado.
Por el mensajes que describes me suena a que la variable parent esta tomando un valor nulo
Cuando abres el form hijo tienes en cuenta de pasarle en el metodo Show() el valor this ?
Form2 formAdd = new Form2();
formAdd.Show(this);
Como muestran estas lineas,
esto es lo que hace disponible que el la propiedad Owner pueda usarse
saludos
hola, funciona super bien tu ejemplo, pero tengo un problema no puedo implementar en un mdiparent, es decir agregar un row en un dgw en un mdi desde una form, lo intento y me abre un nuevo dgv .. gracias por la ayuda
Eliminarhola
EliminarTe abre un nuevo dgv? no sera que abre un nuevo form
Recuerda que no debes usar el "new" para crear una instancia del form, sino que debes acceder a la instancia existente
Debes pasar los datos usando la instancia existente, analiza esta otra tecnica
Comunicar Formularios
esta aplica en ambientes con o sin mdi
saludos
Gracias Leo no pense que respondias tan rapido jeje, era lo que decias me faltaba el this y ya pude bajar el ejemplo muchas gracias.-
ResponderEliminarhola me gustaria, saber como paso los datos seleccionados de un data grid a otro datagrid que esta en otro formulario . Se lo agradeceria que me ayudara.
ResponderEliminarhola amarilis
ResponderEliminarImagino quieres pasar esta fila a un formulario hijo, o sea que estas abriendo ?
Si es asi podrias usar el constructor de ese form que necesita recibir la row seleccionada, o sino propiedades.
En este articulo explico el tema
[WinForms] – Pasaje de información formulario hijo
saludos
Hola leandro esta muy bueno el tutorial pero la verdad si especificamente puedes decirmo como pasar los datos de la fila a la que diera doble click al otro datagridview en este caso del grid1 al grid2
ResponderEliminarLeandro te agradeceria mucho la ayuda mi correo es harvy.vanegas@gamil.com
hola Harvy
ResponderEliminarla tecnica es la misma, solo que ne lugar de programar la accion en los botones usarias el evento
CellDoubleClick
recuerda que en este evento tienes el
e.RowIndex, para poder reconocer en que fila se realizo ese doble clik
detectado esto el resto es identico al del boton que implementa el articulo
saludos
Hola Leandro antes que nada gracias por la ayuda fijate que publique un nuevo tema en mi foro sobre esto es bastante parecido me gustaria que lo vieras y me des tu opinion.
ResponderEliminarhttp://sonnysoft.foroes.net/t87-pasar-datos-de-un-datagridview-a-otro-datagridview-en-distentos-formularios-tutorial#98
hola Harvy
ResponderEliminarrevise el articulo y puedo comentarte varios puntos
- no veo que dejaras en ningun link el codigo con el ejemplo que has desarrollado, con una imagen de solo 3 lineas de codigo se puede apreciar muy poco la solucion. podrias usar skydrive para publicar el codigo
- algo que no queda claro en el codigo es que seria "frmFacturacion", es la instancia , es la clase del formularios, que es ?
porque para acceder a los controlas deberias pasar la instancia
- ademas la idea que intento promover es que no se acople la comunicacion (imagino no era es la idea de tu articulo), se que no es tan directo como acceder como lo haces (tampoco era la idea que sea facil), pero si trae otras ventajas en cuanto a la mantenibilidad y la posibilidad de reutilizar el codigo
saludos
Bueno si Leandro tienes razón como que explico muy poco... De ser mi maestro de Programación ya me hubieses reprobado jeje... Con relación al skyDrive no lo sé usar o al menos nunca lo he probado.
ResponderEliminarHola Leandro antes que nada felicitarte por tu excelente tuto, mi problema sucede que al implementarlo en mi proyecto, me genera un error-->
ResponderEliminarIAddItem parent = this.Owner as IAddItem;
en esa parte de codigo, me genera una excepcion nula, revise el show(this) del formulario padre, por lo que al debuggear el owner si esta lleno, pero en si la sentencia completa(this.Owner as IAddItem) muestra null. Agradeceria tu ayuda.
Ya lo revise y es por uso de un MDI container que tengo en mi proyecto, asi q probando agregue un Form3 a tu proyecto de tipo MDI que invoque al Form1 y me genera el mismo error, aun no se como solucionarlo.
ResponderEliminarhola Jose
ResponderEliminarpero la interfaz IAddItem es implementada por el form que invoca al hijo ?
recuera que el forma deberia definir esta en su declaracion
public class Form3 : Form, IAddItem {
}
es importante que la implemente sino al castear seguro sera null
saludos
Hola, bueno si la interfaz esta en mi formulario padre, pero para que me entiendas mejor, no se si pudieses crear a tu proyecto un Form3 q sea mdi y que llame al form1, te saldra la misma excepcion que a mi, ahora veo que el owner lo toma al mdi(form3) y no al padre(form1), si me pudieses ayudar, saludos y gracias.
ResponderEliminarhola Jose
ResponderEliminarpero si estas trabajando en un ambiente mdi el owner no aplica, no puedes usarlo, como explico aqui
Comunicar formularios MDI
saludos
Bueno no se si lo mío tenga que ver con éste tema pero bueno, mi problema es que quiero pasar los datos de una columna de un datagridview a una columna d otro datagridview que está en otro formulario, el ingreso de datos lo hago por medio de calculos matemáticos, es decir que no utilizo ninguna conexión con BD... Estoy tratando de realizar una prueba de chi-cuadrado... Ayudenme a resolver mi problemas por favor... Éste s mi correo tooplay21@hotmail.com...
ResponderEliminarPD: Es de urgencia
hola tooplay21
ResponderEliminarpero este otro formulario al cual quieres pasarle la informacion es un form hijo ? o sea desde el form donde tienes el grid es el form padre y abres otro form al cual le pasas la info
si es asi recuerda que puedes usar el constructor o propiedades del form hijo para asignar la informacion
[WinForms] – Pasaje de información formulario hijo
de esta forma es que pasarias una lista de datos que necesitas en el otro formulario
saludos
hola leandro primero te felicito por tu blog me ayudo bastante pero me di cuenta que en tu ejemplo solo pasar una fila en distintos formularios mi pregunta es si se pueden pasar varias filas a la vez osea dos registro? me podrias mostrar un ejemplo de como pasar varios registro
ResponderEliminargracias y saludos
hola Ascencio
ResponderEliminarclaro porque no
solo sera cuestion de usar un List<> del objeto que quieras pasar de un form a otro
la lista permitira pasar uno o mas objetos
saludos
hola leandro
ResponderEliminarmuchas gracias por el dato solo tengo una duda el list va en la interface o en el boton donde agrega los campos
gracias y saludos
hola Ascencio
ResponderEliminaren ambos, lo usas para definir el metodo o propiedad de intercambio pore so debe ir en el interfaz
pero tambien lo usarias cuando implementas la interfaz en la clase concreta
saludos
hola leandro me podrias enviar un ejemplo de como hacerlo mi correo es angel_aspe@hotmail.com
ResponderEliminargracias y saludos
hola Ascencio
ResponderEliminarla verdad no tengo armado nada parecido, pero no veo que sea complicado
digo si sabes insertar y rrecuperar registros en tu db solo es cuestion de poner dosc campos de coordenadas para guardar la posicion de cada control que se cree dinamicamente
y luego recuperarlo y usar
int x= Convert.ToInt(row["X"]);
int y= Convert.ToInt(row["Y"]);
Label lbl1 = new Label();
lbl1.Localtion = new Point(x, y);
donde use row sera el Datarow de un datatable que usarias para recuperar la info de la tabla
saludos
Increible Leandro, gracias por todos tus aportes....
ResponderEliminarTengo una duda y ojala me puedas ayudar; sucede que desde un form padre abro un hijo (el padre no se cierra, siempre esta abierto) al estar en el form hijo selecciono (doble click) una fila de un datagridview y cierro el form hijo, pero al estar nuevamente en el form padre no me muestra la fila seleccionada del form hijo, que ya esta cerrado. Gracias de antemano...
hola abel_c_b
ResponderEliminaranalzia el codigo del boton "buscar" de este articulo
[N-Tier] – Desarrollo en capas - Ejemplo Facturación – Parte 1
creo que es la funcionalidad que describes
recuerda que al form hijo desde el padre debes acceder con la instancia del form, puedes poner breakpoint en el codigo para inspeccionar el estado de las variables
saludos
Hola leandro
ResponderEliminarprimero queria felicitarte y agradacerte por las aportaciones de tu blog
soy algo nuevo en programacion y queria ver si podrias orientarme un poco
tengo un proyecto con varias formas (cada una con un datagrid) y estas interactuan con una bd en sql 2005, ademas tambien tengo varias clases
en una clase (llamada conexion) tengo definida la conexion, al dar click en un boton(por ejemplo alta) mando a llamdar una fucion de esa clase, le mando un string(en ese string tengo definido el query) la funcion recibe el string y hace la consulta
la idea es que en esa clase definir una funcion, y desde la forma mandarla a llamar para que haga una consulta(en ese caso un select) y la informacion la llene en el datagrid de la forma, solo que ando un poquito trabado en eso
ese es mi problema espero y pudieras orientarme
gracias de antemano. saludos
Hola leandro..qisiera saber como hago para dar doble click en una fila del grid view y asi abrir otro form pasando los valores de una columna sin utilizar el evento gridviewslectedchanging solo dando doble click a una fila determinada
ResponderEliminarhola daniel
ResponderEliminarpero tu aplicacion es web o winforms ? o sea usas el datagridview o el gridview
si la aplicacion es winforms podrias usar el evento
DataGridView.CellDoubleClick Event
saludos
hola bto
ResponderEliminarno recomendaria tomes ese camino de crear una clase que reciba la query, porque seguramente lo diseñaras de forma incorrecta no soportando el uso de parametros
mejor si diseñas desarollando en capas
[N-Tier] – Desarrollo en capas - Ejemplo Facturación – Parte 3
como veras la capa de datos define la conexion y realiza la query pero orientada al negocio, la conexion la defines en el archivo de configuracion
saludos
Comprendí completamente como utilizar la interfaz y pasar los registros. Tengo duda de algunas líneas de código. Como por ejemplo:
ResponderEliminarstring item = row.Cells["item"].Value.ToString();
¿Eso quiere decir que si el valor que el form hijo me va a pasar es de tipo int me causará problemas?
Otro es el datatable. ¿Que sucede cuando los datos que deseo pasar provienen de una base de datos?
Mi implementación la estoy realizando en 3 capas. Ya vi tus ejemplos y son realmente complicados a pesar de la explicación que das.
Saludos.
hola WilO Frias
ResponderEliminaren realidad esa conversion a string se realiza porque simplemente se espera un texto, pero si sabes que es un valor numerico puedes convertirlo sin problema
lo que si recomendaria es que uses el int.TryParse() para poder convertir sin que se produzca un exception si es que no puede lograrlo
que los datos vengan de la base de datos no deberia afectar en nada, ya questo de comunicar formulario se da en la presentacion, despues si la opcion vieno de una query a la db o si lo asignaste por otro medio es indistinto no deberia afectar al resto de las capas como comunicas la parte visual
saludos
Hola Leandro buenas noches, tu ejemplo me sirvio bastante, te lo agradesco, pero me surgio una duda, si tengo un datagridview con un DataGridViewCheckBoxColumn y quiero pasar varios registros al a vez, como seria.
ResponderEliminarGracias
hola Jonathan
ResponderEliminarno entendi como un combo en el grid afectaria la info que enviarias
se supone que el combo solo toma un unico dato seleccionado
igualmente podrias definir en el constructor o propiedad una List<> para pasar varios items
saludos
hola leandro, gracias por responder, yo me referia a una columnas de ChekBox para seleccionar multiples filas para luego pasarlos a otro datagridview de otro formulario.
ResponderEliminarAunque me haz dado la solucion: "definir en el constructor o propiedad una List<> para pasar varios items".
Gracias,
hola
ResponderEliminarahh era una columna checkbox habia leido mal el tipo de columan a la cual hacias referencia
igualmente la respuesta seria la misma usa un List<> para pasar las filas seleccionadas
saludos
En el supuesto caso cuando ya tenemos herencia ,por ej. en mis forms heredan de DotNetBar de unas plantillas de office 2007, en este caso no es posible realizar tu ejemplo,no? porque lei que en c# o vb no viene la posibilidad de herencia multiple, en dicho caso solo es posible el pasaje entre distintos datagridview en distintos
ResponderEliminarforms por ej. definiendo variables globales o publicas en el form que va a recibir el dato y en donde se manda los datos indicar columna x columna de una fila el valor que tiene el datagridview que quiero mover el dato?
hola Andres
ResponderEliminarno veo que relacion tiene la herencia multiple con el hecho de pasar datos entre formularios
hay otras tecnicas ademas de definir variables globales que se pueden utilizar para pasar datos entre forms
en este articulo explico una que podrias utilizar, que sea un datagridview o algun grid de terceros la tecnica seria la misma, quizas cambie el tipo de datos
pero no se necesite de ninguna herencia para esto
saludos
Buenas Leandro, tengo un problema... Esto podría aplicarse a un datagridview del form padre enlazado a datos? Es que me esta dando problemas.
ResponderEliminarSi es así como tendria que ser?
hola Mikel
ResponderEliminarsi podrias aplicarlo, aunque quizas tambien deberias analizar
[DataGridView] – Pasar Registros entre Grillas
porque si el grid esta enlazado a datos deberias asignar el nuevo item en los datos del grid tiene asinado al datasource
saludos
buen dia amigos: tengo una super pregunta tengo un formulario (agenda) en el pongo un numero y una descripcion,(los mando a guardar en una tabla (agenda)con los siguientes campos numero, texto,tratado) luego mando a llamar esos datos de mi base en otro formulario (puntos tratados) donde tengo un campo que se llama tratado ese campo esta definido como boolean lo que quiero hacer es seleccionar ese CheckBox y decir de la agenda ese punto fue tratado en la reunion y guardarlo en mi tabla agenda ojala puedas ayudarme. gracias!!!
ResponderEliminarhola Marco
ResponderEliminarcuando creas el registro en agenda que vlaor pones en el campo tratado ? le pones false
si tienes un valor bool que recuperas de la db simplemente podrias hacer
chkTratado.Checked = Convert.ToBoolean(reader["tratado"]);
con esto asignas la marca o no segun el vlaor que tenga en la tabla
"reader" es un Datareader, pero se podria hacer para un DataTable de forma similar
saludos
Hola Leandro antes que nada muchas gracias por ayudarnos con este aporte tuyo, ahora lo estoy siguiendo, pero el link de skydrive esta caido, no se si pudieras ayudarme volviendolo a subir. De antemano gracias
ResponderEliminarBuen día. Gracias por el tutorial. Una consulta si no es mucha molestia. Como le hago para evitar que se envie el mismo registo(articulo) a el formulario padre. Es decir si ya se envio una vez, evitar que se vuelva a enviar.
ResponderEliminarEspero me puedas orientar con esta duda.
Saludos
hola frank
EliminarPodrias validarlo, o sea deja que el usuario seleccione el item que quiera pero al enviarlo al otro form revisas si ese dato ya existe
Si ya esta presente le informas mediante un mensaje y no lo agregas
Podrias evitar cerrar el form hijo si es que se da este caso, el metodo que implementas en la interface devuelva un bool indicando si lo agrego o no
saludos
Hola Leandro. Buen dia
EliminarHe estado buscando y encontre esta funcion para buscar si ya escite el dato dentro del datagridview del form padre.
#Region "IAddItem Members"
Public Function AddNewItem(ByVal row As DataGridViewRow) As Boolean Implements IAddItem.AddNewItem
If Not ExisteEndgv(True) Then
Dim Producto As String = row.Cells("columnId").Value.ToString()
Dim Descripcion As String = row.Cells("columnDescripcion").Value.ToString()
Dim Precio As Decimal = row.Cells("ColumnPrecio").Value.ToString()
Me.DataGridView1.Rows.Add(New String() {Producto, Descripcion, Precio})
Return True
End If
Return False
End Function
#End Region
Private Function ExisteEndgv(ByVal producto As String) As Boolean
Dim existe As Boolean = False
For Each fila As DataGridViewRow In DataGridView1.Rows
Dim verificar As String = Convert.ToString(fila.Cells("CProducto").Value)
If producto = verificar Then
existe = True
End If
Next
Return existe
End Function
La interfaz la tengo asi
Interface IAddItem
Function AddNewItem(ByVal row As DataGridViewRow) As Boolean
End Interface
Lo que nose es como hacerle para llamar a la funcion dentro del form hijo
Private Sub dgvDatos_CellDoubleClick(sender As Object, e As DataGridViewCellEventArgs) Handles dgvDatos.CellDoubleClick
Try
Dim row As DataGridViewRow = TryCast(Me.dgvDatos.SelectedRows(0), DataGridViewRow)
Dim parent As IAddItem = TryCast(Me.Owner, IAddItem)
parent.AddNewItem(row)
Me.Close()
Catch ex As Exception
MessageBox.Show(String.Format("Error : {0}", ex.Message), "Error Inesperado", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
hola
Eliminarlo primcipal aqui es como abres el form hijo, alli veo que usas el owner por lo que deberia ser
FormHijo frm = new FormHijo();
frm.Show(this);
ese this que uso en el show es quien asigna la instancia del form padre que implementa la interfaz, asi es como tendras el owner para poder castear a la interface, pudiendo invocar el metodo que expone
saludos
tengo 4 formulario , uno de ellos es MDI, Y los otros son hijo, en el primer formulario tengo que ingresar datos al data grid y almacenarlos temporal y NO utilizar base de datos.
ResponderEliminarMDI: tiene menu strip: catalogo y seleccion del produto. y tambien toolstrip :agregar,facturar y buscar.
LUEGO
al dar clic al formulario seleccionar prod, me abre el formulario dentro de este tengo otro data grid y un texbox de buscar,,, solo que ingreso el nombre de la marca que deseo buscar ; pero tengo que dar clic al boton de busqueda del datagrid. y asi hace el proceso de busqueda.
luego tengo que enviar estos datos a la de factura ya con su importe total , que tambien es un data grid.
hola
Eliminarpero cual seria el problema ? solo planteas la situacion de como los forms se abren
Si el problema es que son form MDI puede resolverlo aplicado esta tecnica
Comunicar Formularios
saludos
Este blog a estas alturas esta salvando mi semestre gracias por el aporte
ResponderEliminarHola Leandro soy nuevo en la programacion de vb.net y estoy actualizando un programa hecho en vb6 a vb.net.
ResponderEliminarTengo mi formulario "Productos" en el cual medante un boton me abre otro form (ListaProductos) en este form unicamente esta un datagridview de 5 columnas que muestra todos los productos existentes y algunas propiedades y un boton de aceptar.
como le hago para que al momento de seleccionar una linea del DGV y oprimir el boton de aceptar se me cierre el form ListaProductos y el campo de "nombre"(columna 2) se pase al txtBuscar que tengo en el form de Productos y se active el metodo click del boton Buscar.
estas son las lineas que quiero generar en vb.net
ListaProductosForm
Private Sub btnAceptar_Click()
ProductosForm.txtBuscar.text = Trim(GridList.selectedItem.SubItems(1))
ProductosForm.btnBuscar_Click
Unload ListaProductosForm
Hola
EliminarPodrias aplicar la tecnica de este articulo
Comunicar Formularios
como veras defines una interfaz para que desde el form del grid puedas pasar datos a la instancia del forma padre
saludos