Introducción
Es muy común cuando se desarrolla con formularios tener la necesidad de comunicarlos de pasar información entre ellos, pudiendo trabajar con la selección de ciertos datos, o especificar algún valor que se asignara en algún control, etc
Este articulo intentara explicar cuales son las mejores formas de realizar estas operaciones.
En artículos previos se ha comentado como pasar información de un formulario hijo al padre, o aquel que realizo la apertura.
En esta oportunidad se atacara la comunicación del padre al hijo, o sea se pasara información al momento de realizar la apertura del formulario.
Existen dos técnicas que pueden aplicarse en este caso:
- haciendo uso del constructor del formulario
- por medio de propiedades
1 – Uso del Constructor del formulario
Una de las opciones pasa pasar información entre formularios es por medio del constructor.
Debe tenerse en cuenta que en .net los formularios son en definitiva clases, por lo tanto puede aplicarse los mismo conceptos orientados a objetos.
EJEMPLO 1
Empezaremos por un ejemplo simple, en donde solo se pasara un valor del formulario denominado “Principal”, a otro formulario denominado “Detalle” que tomara este valor y lo mostrara en un TextBox.
Formulario Detalle
[C#]
public partial class frmDetalle : Form { private int? idbusqueda = null; public frmDetalle() { InitializeComponent(); } public frmDetalle(int idbusqueda) : this() { this.idbusqueda = idbusqueda; } private void frmDetalle_Load(object sender, EventArgs e) { if(idbusqueda.HasValue) txtIdBusqueda.Text = Convert.ToString(idbusqueda); } }
[VB.NET]
Public Partial Class frmDetalle Inherits Form Private _idbusqueda As System.Nullable(Of Integer) = Nothing Public Sub New() InitializeComponent() End Sub Public Sub New(idbusqueda As Integer) Me.New() Me._idbusqueda = idbusqueda End Sub Private Sub frmDetalle_Load(sender As Object, e As EventArgs) If _idbusqueda.HasValue Then txtIdBusqueda.Text = Convert.ToString(_idbusqueda) End If End Sub End Class
En este código se puede apreciar como se ha creado un nuevo constructor en la clase del formulario agregando al mismo un parámetro en donde se indica el id que debe trabajarse.
Un punto importante a destacar es que al pasar la información en el constructor no se realice la asignación directamente en un control del formulario, sino que recomendable hacer uso variable privadas para contener valor que luego en el evento Load o en algún otro evento se haga efectiva la asignación si es necesaria.
Esto es así porque en la etapa de construcción de la clase del formulario los controles aun no están inicializados, por lo tanto una asignación en ese punto puede traer problemas.
En el caso de este ejemplo se veras que la variable privada ha sido declarada para soportar valores nulos, se realizo de esta forma ya que se ha dejado el constructor del formulario sin parámetros, en caso de que no quiera especificarse valor de búsqueda al momento de instanciar el formulario.
En caso de darse la situación en que sea necesario usar el formulario sin pasar un valor determinado, esta situación es verificada en el evento Load y así determinar la asignación un valor a la variable o no.
Formulario Principal
[C#]
public partial class frmPrincipal : Form { public frmPrincipal() { InitializeComponent(); } private void btnBuscar_Click(object sender, EventArgs e) { int idbusqueda = Convert.ToInt32(txtBusqueda.Text); frmDetalle form = new frmDetalle(idbusqueda); form.Show(); } }
[VB.NET]
Public Partial Class frmPrincipal Inherits Form Public Sub New() InitializeComponent() End Sub Private Sub btnBuscar_Click(ByVal sender As Object, ByVal e As EventArgs) Dim idbusqueda As Integer = Convert.ToInt32(txtBusqueda.Text) Dim form As New frmDetalle(idbusqueda) form.Show() End Sub End Class
El formulario denominado Padre o Principal encargado de hacer la llamada y de pasa el valor al formulario Hijo es bastante simple, solamente cuenta con un botón el cual al ejecutarse crea una instancia del formulario a invocar pasándole allí mismo el valor que el usuario ingreso en el TextBox, y por ultimo invoca al método Show() para que se desplegué el formulario.
[C#]
|
[VB.NET]
|
EJEMPLO 2
En este punto aplicaremos el mismo concepto que el ejemplo anterior solo que lo haremos algo mas complejo.
No solo vamos a enviar como valor al segundo formulario un simple dato, en este caso será toda una colección de ítems seleccionados en un DataGridView,
Formulario Detalle
[C#]
public partial class frmDetalle : Form { private int _maxPrecio; private List<DataRow> _listDataRow = null; private List<Productos> _listProducto = null; private frmDetalle() { InitializeComponent(); } public frmDetalle(List<DataRow> items) : this(items, 3200) { } public frmDetalle(List<Productos> items) : this(items, 3200) { } public frmDetalle(List<DataRow> items, int maxPrecio) : this() { this._listDataRow = items; this._maxPrecio = maxPrecio; } public frmDetalle(List<Productos> items, int maxPrecio) : this() { this._listProducto = items; this._maxPrecio = maxPrecio; } private void frmDetalle_Load(object sender, EventArgs e) { // // Cargo los items provenientes del constructor con DataRows // if (_listDataRow != null) { foreach (DataRow row in _listDataRow) { dtgDetalles.Rows.Add(row.ItemArray); } } // // Cargo los items provenientes del constructor // con entidades de la clase Producto // if (_listProducto != null) { dtgDetalles.AutoGenerateColumns = false; dtgDetalles.DataSource = _listProducto; } } private void dtgDetalles_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { if (dtgDetalles.Columns[e.ColumnIndex].Name == "Precio") { if (Convert.ToInt32(e.Value) > _maxPrecio) dtgDetalles.Rows[e.RowIndex].DefaultCellStyle.ForeColor = Color.Red; } } public class Productos { public int IdProducto { get; set; } public string Descripcion { get; set; } public int Precio { get; set; } } }
[VB.NET]
Public Partial Class frmDetalle Inherits Form Private _maxPrecio As Integer Private _listDataRow As List(Of DataRow) = Nothing Private _listProducto As List(Of Productos) = Nothing Private Sub New() InitializeComponent() End Sub Public Sub New(items As List(Of DataRow)) Me.New(items, 3200) End Sub Public Sub New(items As List(Of Productos)) Me.New(items, 3200) End Sub Public Sub New(items As List(Of DataRow), maxPrecio As Integer) Me.New() Me._listDataRow = items Me._maxPrecio = maxPrecio End Sub Public Sub New(items As List(Of Productos), maxPrecio As Integer) Me.New() Me._listProducto = items Me._maxPrecio = maxPrecio End Sub Private Sub frmDetalle_Load(sender As Object, e As EventArgs) ' ' Cargo los items provenientes del constructor con DataRows ' If _listDataRow IsNot Nothing Then For Each row As DataRow In _listDataRow dtgDetalles.Rows.Add(row.ItemArray) Next End If ' ' Cargo los items provenientes del constructor ' con entidades de la clase Producto ' If _listProducto IsNot Nothing Then dtgDetalles.AutoGenerateColumns = False dtgDetalles.DataSource = _listProducto End If End Sub Private Sub dtgDetalles_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) If dtgDetalles.Columns(e.ColumnIndex).Name = "Precio" Then If Convert.ToInt32(e.Value) > _maxPrecio Then dtgDetalles.Rows(e.RowIndex).DefaultCellStyle.ForeColor = Color.Red End If End If End Sub Public Class Productos Private _IdProducto As Integer Public Property IdProducto() As Integer Get Return _IdProducto End Get Set(ByVal value As Integer) _IdProducto = value End Set End Property Private _Descripcion As String Public Property Descripcion() As String Get Return _Descripcion End Get Set(ByVal value As String) _Descripcion = value End Set End Property Private _Precio As Integer Public Property Precio() As Integer Get Return _Precio End Get Set(ByVal value As Integer) _Precio = value End Set End Property End Class End Class
Este código tiene bastante para comentar, en primer lugar es interesante analizar como se han definido varios constructores para el formulario, los cuales abarcan distintos tipos de colecciones, que podrá ser enviada al mismo para ser desplegada en el formulario de detalle.
Entre las opciones disponibles esta una lista de DataRow, o la carga de una clase custom que representa a los productos. Además en los constructores esta la posibilidad de definir un valor de precio máximo, el cual cumplirá la función de definir que registros de la grilla aparecerán con letras rojas según se haya excedido ese monto, sino se especifica valor (al optar el uso del constructor sin este parámetro), se define un valor por defecto de 3200.
Algo importante a marcar es la definición del constructor sin parámetros como privado, esto permite que sea invocado desde dentro de la clase, pero no desde fuera, es por eso que los constructores con parámetros lo terminan utilizan, cuando haces :this(), para inicializar los controles del formulario, pero desde fuera quien cree la instancia deberá obligativamente definir los valores de los ítems a cargar en la grilla.
Dentro del evento Load del formulario se valida que lista de datos se ha cargado y se procede con la carga del mismo, como se vera cada lista tiene su particularidad en el método con que carga la información en el DataGridView.
Además se hizo uso del evento CellFormatting, y como juega el valor de precio máximo para definir que filas de la grilla deben ir en color, en este caso definido con rojo.
Formulario Principal
[C#]
private void btnMostrarSeleccionDataRow_Click(object sender, EventArgs e) { List<DataRow> items = new List<DataRow>(); foreach (DataGridViewRow row in dataGridView1.SelectedRows) { DataRowView dataItem = row.DataBoundItem as DataRowView; items.Add(dataItem.Row); } frmDetalle form = new frmDetalle(items); form.Show(); } private void btnMostrarSeleccionEntidades_Click(object sender, EventArgs e) { List<frmDetalle.Productos> items = new List<frmDetalle.Productos>(); foreach (DataGridViewRow row in dataGridView1.SelectedRows) { frmDetalle.Productos producto = new frmDetalle.Productos() { IdProducto = Convert.ToInt32(row.Cells["IdProducto"].Value), Descripcion = Convert.ToString(row.Cells["Descripcion"].Value), Precio = Convert.ToInt32(row.Cells["Precio"].Value), }; items.Add(producto); } frmDetalle form = new frmDetalle(items); form.Show(); }
[VB.NET]
Private Sub btnMostrarSeleccionDataRow_Click(ByVal sender As Object, ByVal e As EventArgs) Dim items As New List(Of DataRow)() For Each row As DataGridViewRow In dataGridView1.SelectedRows Dim dataItem As DataRowView = TryCast(row.DataBoundItem, DataRowView) items.Add(dataItem.Row) Next Dim form As New frmDetalle(items) form.Show() End Sub Private Sub btnMostrarSeleccionEntidades_Click(ByVal sender As Object, ByVal e As EventArgs) Dim items As New List(Of frmDetalle.Productos)() For Each row As DataGridViewRow In dataGridView1.SelectedRows Dim producto As New frmDetalle.Productos() producto.IdProducto = CInt(row.Cells("IdProducto").Value) producto.Descripcion = CStr(row.Cells("Descripcion").Value) producto.Precio = CInt(row.Cells("Precio").Value) items.Add(producto) Next Dim form As New frmDetalle(items) form.Show() End Sub
Del formulario Padre o Principal que realiza la llamada, es importante notar los dos métodos utilizados para pasar la mismos registros seleccionados, pero utilizando distintos constructores del formulario Hijo o Detalle.
En el primero se toma la información usada como origen de datos al DataGridView, transformado este en un DataRow, en el segundo método se construye una entidad independiente en base a la información e la misma.
[C#]
|
[VB.NET]
|
2 – Uso de Propiedades
Esta es otra de las técnicas que pueden utilizarse para pasar información entre formularios, por ahí no es tan restrictivo al momento de inicializar el formulario como el uso de constructores, ya que en este método el constructor será único y sin parámetros, las propiedades definirán los atributos que podrán asignarse.
Para este caso se implementaran los mismo ejemplos anteriores pero con el uso de propiedades esto permitirá la comparación y así analizar que técnica resulta mas conveniente, como en todo desarrollo no hay una regla que diga que esta bien y que mal, será cuestión de aplicar los criterios que uno crea mas razonables y seleccionar que método aplicar.
EJEMPLO 1
Formulario Detalle
[C#]
public partial class frmDetalle : Form { private int? _idbusqueda = null; public int IdBusqueda { set { _idbusqueda = value; } } public frmDetalle() { InitializeComponent(); } private void frmDetalle_Load(object sender, EventArgs e) { if (_idbusqueda.HasValue) txtIdBusqueda.Text = Convert.ToString(_idbusqueda); } }
[VB.NET]
Public Partial Class frmDetalle Inherits Form Private _idbusqueda As System.Nullable(Of Integer) = Nothing Public WriteOnly Property IdBusqueda() As Integer Set _idbusqueda = value End Set End Property Public Sub New() InitializeComponent() End Sub Private Sub frmDetalle_Load(sender As Object, e As EventArgs) If _idbusqueda.HasValue Then txtIdBusqueda.Text = Convert.ToString(_idbusqueda) End If End Sub End Class
En este caso se ha creado una propiedad de nombre IdBusqueda, definida para que solo pueda ser establecido su valor, pero no su lectura, esto es así porque la idea es luego usar la variable privada para la lógica interna.
Si se compara con el método anterior del constructor el código no ha cambiado mucho, solo se ha dejado un constructor sin parámetros, y se agrego la propiedad.
Formulario Principal
[C#]
public partial class frmPrincipal : Form { public frmPrincipal() { InitializeComponent(); } private void btnBuscar_Click(object sender, EventArgs e) { int idbusqueda = Convert.ToInt32(txtBusqueda.Text); frmDetalle form = new frmDetalle(); form.IdBusqueda = idbusqueda; form.Show(); } }
[VB.NET]
Public Partial Class frmPrincipal Inherits Form Public Sub New() InitializeComponent() End Sub Private Sub btnBuscar_Click(ByVal sender As Object, ByVal e As EventArgs) Dim idbusqueda As Integer = Convert.ToInt32(txtBusqueda.Text) Dim form As New frmDetalle() form.IdBusqueda = idbusqueda form.Show() End Sub End Class
Al crear la instancia ahora se puede hacer libremente sin necesidad de establecer allí mismo un valor como parámetro, pues esto ha sido reemplazado por la línea contigua en donde se utiliza la propiedad creada.
[C#]
|
[VB.NET]
|
EJEMPLO 2
Formulario Detalle
[C#]
public partial class frmDetalle : Form { private int _maxPrecio; private List<DataRow> _listDataRow = null; private List<Productos> _listProducto = null; public List<DataRow> ListaDataRow { set { _listDataRow = value; } } public List<Productos> ListaProducto { set { _listProducto = value; } } public int PrecioMaximo { set { _maxPrecio = value; } } public frmDetalle() { InitializeComponent(); this._maxPrecio = 3200; } private void frmDetalle_Load(object sender, EventArgs e) { // // Cargo los items provenientes del constructor con DataRows // if (_listDataRow != null) { foreach (DataRow row in _listDataRow) { dtgDetalles.Rows.Add(row.ItemArray); } } // // Cargo los items provenientes del constructor // con entidades de la clase Producto // if (_listProducto != null) { dtgDetalles.AutoGenerateColumns = false; dtgDetalles.DataSource = _listProducto; } } private void dtgDetalles_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { if (dtgDetalles.Columns[e.ColumnIndex].Name == "Precio") { if (Convert.ToInt32(e.Value) > _maxPrecio) dtgDetalles.Rows[e.RowIndex].DefaultCellStyle.ForeColor = Color.Red; } } public class Productos { public int IdProducto { get; set; } public string Descripcion { get; set; } public int Precio { get; set; } } }
[VB.NET]
Public Partial Class frmDetalle Inherits Form Private _maxPrecio As Integer Private _listDataRow As List(Of DataRow) = Nothing Private _listProducto As List(Of Productos) = Nothing Public WriteOnly Property ListaDataRow() As List(Of DataRow) Set _listDataRow = value End Set End Property Public WriteOnly Property ListaProducto() As List(Of Productos) Set _listProducto = value End Set End Property Public WriteOnly Property PrecioMaximo() As Integer Set _maxPrecio = value End Set End Property Public Sub New() InitializeComponent() Me._maxPrecio = 3200 End Sub Private Sub frmDetalle_Load(sender As Object, e As EventArgs) ' ' Cargo los items provenientes del constructor con DataRows ' If _listDataRow IsNot Nothing Then For Each row As DataRow In _listDataRow dtgDetalles.Rows.Add(row.ItemArray) Next End If ' ' Cargo los items provenientes del constructor ' con entidades de la clase Producto ' If _listProducto IsNot Nothing Then dtgDetalles.AutoGenerateColumns = False dtgDetalles.DataSource = _listProducto End If End Sub Private Sub dtgDetalles_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) If dtgDetalles.Columns(e.ColumnIndex).Name = "Precio" Then If Convert.ToInt32(e.Value) > _maxPrecio Then dtgDetalles.Rows(e.RowIndex).DefaultCellStyle.ForeColor = Color.Red End If End If End Sub Public Class Productos Private _IdProducto As Integer Public Property IdProducto() As Integer Get Return _IdProducto End Get Set(ByVal value As Integer) _IdProducto = value End Set End Property Private _Descripcion As String Public Property Descripcion() As String Get Return _Descripcion End Get Set(ByVal value As String) _Descripcion = value End Set End Property Private _Precio As Integer Public Property Precio() As Integer Get Return _Precio End Get Set(ByVal value As Integer) _Precio = value End Set End Property End Class End Class
La sección donde se aplica la lógica del formulario si se compara con los ejemplo que usaban un constructor para pasar los valores, no ha cambiado en nada, la única parte que si ha recibido los cambios es en la definición del método en que se asignan los valores a las variables privadas del formulario.
En este caso el constructor sin parámetro vuelve a ser publico, y dentro de este se define valor por defecto para el precio máximo, usado para asignar los colores a las filas de la grilla.
Formulario Principal
[C#]
private void btnMostrarSeleccionDataRow_Click(object sender, EventArgs e) { List<DataRow> items = new List<DataRow>(); foreach (DataGridViewRow row in dataGridView1.SelectedRows) { DataRowView dataItem = row.DataBoundItem as DataRowView; items.Add(dataItem.Row); } frmDetalle form = new frmDetalle(); form.ListaDataRow = items; form.Show(); } private void btnMostrarSeleccionEntidades_Click(object sender, EventArgs e) { List<frmDetalle.Productos> items = new List<frmDetalle.Productos>(); foreach (DataGridViewRow row in dataGridView1.SelectedRows) { frmDetalle.Productos producto = new frmDetalle.Productos() { IdProducto = Convert.ToInt32(row.Cells["IdProducto"].Value), Descripcion = Convert.ToString(row.Cells["Descripcion"].Value), Precio = Convert.ToInt32(row.Cells["Precio"].Value), }; items.Add(producto); } frmDetalle form = new frmDetalle(); form.ListaProducto = items; form.Show(); }
[VB.NET]
Private Sub btnMostrarSeleccionDataRow_Click(sender As Object, e As EventArgs) Dim items As New List(Of DataRow)() For Each row As DataGridViewRow In dataGridView1.SelectedRows Dim dataItem As DataRowView = TryCast(row.DataBoundItem, DataRowView) items.Add(dataItem.Row) Next Dim form As New frmDetalle() form.ListaDataRow = items form.Show() End Sub Private Sub btnMostrarSeleccionEntidades_Click(sender As Object, e As EventArgs) Dim items As New List(Of frmDetalle.Productos)() For Each row As DataGridViewRow In dataGridView1.SelectedRows Dim producto As New frmDetalle.Productos() producto.IdProducto = CInt(row.Cells("IdProducto").Value) producto.Descripcion = CStr(row.Cells("Descripcion").Value) producto.Precio = CInt(row.Cells("Precio").Value) items.Add(producto) Next Dim form As New frmDetalle() form.ListaProducto = items form.Show() End Sub
[C#]
|
[VB.NET]
|
Conclusión
Si bien en este articulo se han explicado dos técnicas para pasar información de un formulario Padre a su Hijo, esto no quiere decir que deba usarse una u otra, por el contrario estas podrían ser complementadas entre si.
En el constructor se podría definir información que es requería para el funcionamiento del formulario que se este invocando, mientras que en las propiedades podría especificarse información opcional.
Leandro,quisiera pedirte opinion.Estoy desaroyando una pequeña aplicacion con base de datos.
ResponderEliminarVarios forms con sus datagrids enlazados a datos,pero necesito pasar
datos entre ellas y tengo problemas al estar enlazados(los datagrids)a datos (ya que soy principiante).Mi pregunta es la siguiente.¿Es conveniente trabajar sin enlazar los datagrids y posteriormente actualizar el dataset?¿O a lo mejor me seria mas sencillo trabajar en modo conectado?.
hola victor,
ResponderEliminarte comento, en realidad la respuesta a tu pregunta no tiene una respuesta concreta, depende de como uses los dataset, es logico que bindearlos a la grilla siempre facilita la codificiacion, ya que el propio datagridview actualiza el datatable que hayas bindeado y puedes sincronizarlo directamente.
Igualmente si necesitas comunicar formularios lo que intento hacer simpre es pasar la minima cantidad de informacion, o sea si necesitas editar la lista de ventas a un cliente, no pases la lista directa desde el formulario padre, sino que solo pasa el id del cliente al otro formulario, (ya sea por propiedad o constructor), y luego trabaja con este dato consultando a la db
bueno espero haber constestado un poco la pregunta
saludos
Gracias Leandro.¡¡Te voy a coser a preguntas!!! ;). ( es broma... ,no voy a abusar de tu buena disposicion a responder a los que empezamos.Un Saludo
ResponderEliminarHola Leandro saludos, agradeciendo tus blogs y ayudas, como siempre muy atento en realizar este tipo de tutoriales. Bonito dia
ResponderEliminaratte:(Dacory)
hola yoyis
ResponderEliminarMe alegro que haya sido de utilidad
saludos
hola, tengo una duda con respecto al tema.
ResponderEliminarQuiero pasar el contenido de un pictureBox de un form2(hijo) al form1(padre).
Ya que en el form2 hago una captura de huella digital y quiero regresarla al formulario padre.
Ojala puedan orientarme.
Saludos!
hola LJ
ResponderEliminarEn ese caso este articulo no servira
analiza este otro
Comunicar formularios de forma desacoplada
veras alli como por medio de interfaces se puede desacoplar la comunicacion de los formulario y maximizar la reutilizacion.
En tu caso podrias pasar entre formulario el objeto Image que tiene asociado el PictureBox
Esta Image lo defines en un metodo de la interfaz
saludos
Hola Leandro, tengo una duda enorme y espero que me puedas ayudar.
ResponderEliminarTengo un formulario llamado FrmInicio, otro formulario llamado FrmHistorial, otro llamado
FrmControlManual y una clase llamda Dispositivo.
El FrmInicio es el que se muestra cuando se inicia la aplicación. El FrmHistorial es un
formulario que se crea (pero no se muestra) en el contructor de FrmInicio, se muestra al
pulsar un botón, mas o menos así:
public class FrmInicio : Form
{
private FrmHistorial historial;
public FrmInicio()
{
InitializeComponent();
historial = new FrmHistorial();
}
private void btnHistorial_Click(object sender, EventArgs e)
{
// Si el formulario se oculto usando Hide(), usar Show() para mostrarlo
historial.Show();
// Si esta activo pero detras de una ventana, darle el foco
historial.Activate();
}
}
FrmHistorial solo contiene un textbox multi-linea y su función es registrar cualquier
cosa que pase en la aplicación. Por ejemplo, si en FrmInicio se pulso otro botón o se
activo/desactivo un checkbox, en el textbox de FrmHistorial se debe adjutar una linea de
texto como "Se activo/desactivo el checkbox #3".
Por otro lado, el formulario FrmControlManual debe ser capaz de hacer lo mismo que
FrmInicio: adjutar lineas de texto en el textbox de FrmHistorial dependiendo de lo que
suceda en FrmControlManual. Además, FrmControlManual es un formulario que es mandado a
llamar por FrmControlInicio.
Por último, la clase Dispositivo, es una clase que envía información por el puerto
serial, y cada vez que eso ocurra, debe registrar en el textbox de FrmHistorial la
información que se ha enviado.
En resumen, multiples formularios deben interactuar con una sola instancia de
FrmHistorial, además de que una clase también debe hacerlo. La restricción es que no
puedo crear un método estático en FrmHistorial para agregar texto, algo como:
public static void AgregarEntrada(string valor)
{
string entrada = String.Format("{0} {1}\r\n", DateTime.Now, valor);
txtAreaDeEventos.AppendText(entrada);
}
porque este afectaría al textbox y este tampoco puede ser estatico.
Otra restricción es que no puedo pasar una referencia de FrmHistorial desde FrmInicio a
FrmControlManual porque según sé, se violaria una regla de la POO y sería un acople muy
grande entre los dos formularios.
Entonces, ¿qué me queda por hacer?
Gracias por la ayuda.
hola Ivanhoe
ResponderEliminarbueno veo que tienes una interaccion entre formularios algo enredada
lo primero que me preguntaria, es necesario toda esa interaccion, no se podria simplificar, quizas disñar un solo form usando Tabs, o diseñar una especie de wizard con bortones de siguiente que vayan capturando la info paso a paso
el tema es que sino tendrias que ir pasando la instancia de los forms al otro con el cual interactua, podrias usar una interfaz para desacoplar la comunicacion pero igualmente esta bastante enredado
saludos
Hola Leandro, tienes razón, es un enredadero de formularios y tampoco me gusta, jeje, vere que puedo hacer. Gracias!!
ResponderEliminarhola Leandro, estoy actualmente desarrolando un sistema de compras en vb.net 2010 y tengo mi form de las compras donde guardo en textbox´s la info de la orden de compra y en otro groupbox hay una serie de textbox´s donde escribo el material junto con cantidad y precio y luego en un boton agregar lo agrego a un datagridview, todo eso lo puedo grabar en sql server, pero quisiera poder crear un report viewer de toda esa info que acabo de mandar a sql al nomas darle guardar. en otras palabras que cuando le de guardar a la info me la guarde en sqk server y me abra el report viewer con esa info para despues imprimirla en pdf word o excel. podrias ayudarme a crear ese rerpotviewer porfavor.
ResponderEliminarhola MIND CORRUPTER
ResponderEliminarimagino apuntabas a usar un reporte de reporting services, o sea crear un .rdlc
si es asi solo es cuestion de agregar el reporte y definiendo un dataset tipado vincularlo a los datos
[Reporting Service] Campo Imagen desde un DataSet Tipado
como veras solo es cuestion de definir un dataset tipado, cargarlo con la info procediente de la db y mostrarlo en el reportviewer
saludos
oye Leandro muchas gracias por atender mis inquietudes, bien mi inquietud consiste en que yo quiero que al momento de darle guardar a mi formulario me aviente el reporte con los datos cargados del form que guardo en sql figurate, cuando guardo de dos tablas una mestro y una detalle en un solo boton utilizo un max en la query para recuperar el ultimo registro almacenado en la tbl maestro y con ese grabo en la detalle, lo que quiero que haga el boton guardar ademas de lo que ya explique es que me abra el reporte y me carge esa info recien guardada o que jale esos datos desde el formulario como en un decir crear el reporte y guardar en bd ojala se pueda, pero aun no he probado el dataset tipeado vere si logro hacerlo y te aviso y espero no te moleste seguir consultandote ok.
ResponderEliminarde antemano muchas gracias.
hola
ResponderEliminarsi tienes el id recien creado puedes recuperar la info basandote en el mismo y cargando el dataset tipado para mostrar el reporte
Recuerda que si la pregunta que necesitas plantear es extenda quizas sea un mejor lugar los foros
Foro vb.net
saludos
gracias Leandro, ahora mi duda es esta rapidito. como actualizar un datagridview al cerrar otro form dicho form graba los datos en labase y en el fomr del dtagrid solo visualizo los datos d ela tabla pero al abrirlo no se ve el ultimo registro que guarde todo esto en ejecucion.. gracias
ResponderEliminarEste comentario ha sido eliminado por el autor.
ResponderEliminarhola MIND CORRUPTER
ResponderEliminarpero si desde un form abres otro que aplica cambios a la tabla, solo es cuestion de detectar desde el primer form cuando se cierra el segundo para aplciar la logica
lo que no has comentado es la forma en que el form1 invoca al form2, usas el ShowDialog() ?
porque si es asi podrias hacer desde el form1 que tiene el datagridview
Form2 frm2 = new Form2();
frm2.ShowDialog();
//aqui cargar con una query el datatable
DataGridView1.DataSource = dt;
de esta forma veras que el showdialog() como detiene la ejecucion al cerrar continua, por eso actualizas
si usas el Show() la cisa cambia un poco, pero basicamente seria adjuntarte al evento FormClosing del form2 cuando creas la instancia
se realizaron varias preguntas sobre esto en el foro:
http://social.msdn.microsoft.com/Forums/es/vbes/thread/508c6966-7a76-4415-810d-74c6af86134a
saludos
de hecho le habia agregado al boton cerrar del form que guarda los datos esta linea
ResponderEliminarForm_ver_señoras.Tbl_señorasTableAdapter.Update
(Form_ver_señoras.ALAMAR_DBDataSet.tbl_señoras)
y con esta tambien
Form_ver_señoras.Tbl_señorasTableAdapter.fill
(Form_ver_señoras.ALAMAR_DBDataSet.tbl_señoras)
bien Leandro, de hecho utilizo el showdialog() porque esto limita de abrir otro a la vez, pues ninguno es padre o hijo sino que los dos se abren desde una toolbar en uno guardo y en el otro solo verifico que se haya agregado con el fin de ver el resultado en runtime, lo que quieor es que al cerrar el form donde escribo me actualize el tableadapter del grid que desplega la vista general de la tabla pues este grid esta creado con un arrastre de elementos del dataset (simple)... gracias de antemano
ResponderEliminarhola Leandro Feliz año, tengo una inquietud acerca de Visual Studio veras, tengo mi proyecto en vb.net y cuando le hago cambios y lo corro me sigue mostrando lo que tenia antes de hacerle cambios por ejeplo tenia un form con 3 tabs le borre una y me sigue mostrando las tres que puedo hacer....
ResponderEliminarhola MIND CORRUPTER
ResponderEliminarno has probado realizar un Clear de la solucion y luego un Rebuild de la misma, esto fuerza la compilacion y actualizacion de lo generado
Tambien podrias ir a las carpetas \bin\Debug y eliminar su contendio para luego compilar
saludos
pues mira leandro te comento que hago clear y rebuild todo bien al correrlo me dice que no encuentra el ejecutable de bin/debug/proyecto.exe
ResponderEliminarya me desespero este asunto.
ya resolvi leandreo gracias simplemente no regeneraba si habian errores pero todo bien gracias....
ResponderEliminarhola Leandro, como stas queria saber si me puedes orientar con un kardex que necesito desarrollar, veras tengo una tabla con compras de materiales y lo que necesito es reflejar el uso de esos materiales y las existencias que qudan de acuerdo a su descargotodo es en vb.net y sql server 2008 gracias de antemano
ResponderEliminarhola MIND CORRUPTER
ResponderEliminarsino entendi mal basicamente apuntas a un sistema de stock de materiales?
para eso solo define en la tabla un campo de Stock, o Existencias que llevara la cantidad que se posee
luego cuando realiza es operaciones que consumen este material simplemente actualizas restando lo que se usa
UPDATE NombreTabla SET stock = stock - @stock WHERE idproducto = @idproducto
como veras esa query actualizaria las existencia restando lo que se va usando
saludos
gracias Leandro de verdad que si lo sacas de apuros a uno, ahora tengo un problema que no creo que sea mucho para ti te cuento: desarrolle una aplicacion de registro de personas en vb.net con conectividad sql server 2008 todo corre bien excepto a la hora que lo pruebo en otra pc me sale que el ejecutable dejo de funcionar y el nombre del evento del problema es CLR20r3 ayuda! pleaseee.
ResponderEliminarperdon que moleste tanto Leandro pero necesito llenar un datagridview de vb.net a partir de un combo con datos de bd osea si yo elijo femenino que me muestre en el grid solo inf de mujeres es un ejemplo pero no hayo como hacerlo ya intente con dataset tipeado pero no funciona gracias de antemano!!!
ResponderEliminarahora con respecto a lo del cardex e inventario como hago para que cuando compre x material y si aun tengo en existencias me lo actualize en el mismo material sin duplicar material gracias
ResponderEliminarhola MIND CORRUPTER
ResponderEliminarme sale que el ejecutable dejo de funcionar y el nombre del evento del problema es CLR20r3
pero solo eso dice, no hay ninguna otra descripcion que detalle el problema ?
es algo dificil decir que podria ser este problema solo con esa descripcion
hay varias preguntas en el foro sobre el tema
http://social.msdn.microsoft.com/Forums/es/vbes/thread/436b042c-20f7-4c6b-809b-e9cc888c573b
http://social.msdn.microsoft.com/Forums/es/vbes/thread/5438744e-edbf-4091-8983-781b05114445
http://social.msdn.microsoft.com/Forums/en-US/clr/thread/4e4134fd-5ad7-404d-854f-eb7e7a0fd0fd
segun veo pareciera temas de componentes que no puede localizar
saludos
hola MIND CORRUPTER
ResponderEliminaren el evento SelectedChangeCommited del combo podrias tomar el valor del mismo y usarlo de filtro para la query que carga el grid
private void combobox1_SelectedChangeCommited(...)
{
DataTable dt = new DataTable();
using (SqlConnection cnn = new SqlConnection("connection string")) {
string query = "SELECT * FROM NombreTabla WHERE campo = @param"
SqlCommand cmd = new SqlCommand(query, cnn);
cmd.Parameters.AddWithValue("@param", Convert.ToInt32(combobox1.SelectedValue));
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
}
DataGridView1.DataSource = dt;
}
saludos
hola MIND CORRUPTER
ResponderEliminarpara actualizar el material solo es cuestion de crear el UPDATE
UPDATE NombreTabla SET stock = stock - @cant WHERE idmaterial = @id
o sea si le pasas esos dos valores por parametro, la cantidad que quieres quitar de materiales y el producto que debe afectar
saludos
muy bien leandro muchas gracias por responder a nuestras dudas, ahora molesto con esto como hago para guardar lo de un grid en dos tablas al mismo tiempo osea 7 campos into tabla 1 y 3 registros into tabla 2
ResponderEliminarlos registros son del mismo form envb.net y respecto al errror que te mencione solo eso dice es un from que te da opcion de cerral el programa depurar o buscar en linea gracias.........
y con respecto al grid alimentado por combo si me funciono a escepcion de que hay un item del combo que despliega 5 registros solo que en el grid me alterna una fila con registros a la izquierda y la siguiente con registros centrados, cabe menconar que el grid no tiene encabezados creados esta vacio.
ResponderEliminarno entiendo porque los muestar asi graciasssss.....
Leandro fijate que me surge otra inquietud. tengo mi proyecto y cuando lo quiero probar en otro visual studio de otra pc me da error por la instancia de sql server le cambio a la conexion de bd y nada funnciona como puedo hacer para dejar relativa una conexion de sql para que se conecte con cualquier nombre de servidor sql para poderlo instalar en cualquier computadora...gracias
ResponderEliminarhola MIND CORRUPTER
ResponderEliminarpara grabar en varias tablas podrias ahcer como se menciona aqui
[N-Tier] – Desarrollo en capas - Ejemplo Facturación – Parte 1
para persistir las facturas y sus detalles
como veras vas recorriendo cada registro y lo impactas en la tabla que corresponde con su command especifico
puedes crear varios command de ado.net y tomar los campos que cada INSERT requiera
saludos
hola MIND CORRUPTER
ResponderEliminarcon respecto a la alineacion la verdad es raro, no sabria decirte que lo podria causar
quizas que sean numeros o letras el contrnido, causando varie esta alineacion, estilo excel, pero es extraño
si defines cada columan en tiempo de diseño valida las propiedades para ver si alguna define la alineacion
saludos
hola MIND CORRUPTER
ResponderEliminarpodrias usar en el connection string
Data Source=.\SQLEXPRESS ....
de esta forma ahces referencia a la pc local
eso si deberias tenr sql instalado en la pc de desarrollo, junto al VS
saludos
gracias Leandro pero estoy trabajando en una aplicación de vb.net y sql server que se supone estara en 2 pc´s con la misma base alojada en el servidor y tengo entendido que cuando es sql server requiere la instancia y quiero saber como hacer para que trabaje en cualquier maquina que lo instale sin tener que cambiar eso en la cadena de conexion lo del express si lo sabia pero es sql server y tengo ese problema no se si me entiendas....gracias
ResponderEliminarleandro que tal gracias por tu ayuda una consulta con codigo tengo este
ResponderEliminarPrivate Sub ComboBox4_SelectionChangeCommitted(sender As Object, e As System.EventArgs) Handles ComboBox4.SelectionChangeCommitted
Dim sql As String
Dim cnn As SqlConnection
Dim cmd As SqlCommand
Dim da As SqlDataAdapter
Dim ds As DataSet
Dim dt As New DataTable
Dim conexion As String = "Data Source=RAZIEL-PC\RAZIEL;Initial Catalog=OVISA_DB;Integrated Security=true"
cnn = New SqlConnection(conexion)
cnn.Open()
sql = "SELECT unidad_medida FROM tbl_items where tbl_items.id_subcategoria = '" & ComboBox3.SelectedValue & "'"
cmd = New SqlCommand()
cmd.CommandText = sql
cmd.CommandType = CommandType.Text
cmd.Connection = cnn
da = New SqlDataAdapter(cmd)
ds = New DataSet()
da.Fill(ds)
da.Fill(dt)
TextBox3.Text = dt.Rows(0).Item("unidad_medida").ToString
End Sub
la cuestion que el codigo al seleccionar un combo me filtra un valor a un textbox pero al cambiar de seleccion en combo no cambia en el text en que puedo estar fallando.............gracias
hola MIND CORRUPTER
ResponderEliminarpara conectarte a sql server, si es una version express
Enable Remote Connection on SQL Server 2008 Express
por supuesto deberas validar que el firewall no bloquee las conexiones
y luego en el connection string definir el nombre o ip de esa pc
puedes definir en el connection string
Filtros Condicionales (1/2)
saludos
hola MIND CORRUPTER
ResponderEliminarveo que aqui
sql = "SELECT unidad_medida FROM tbl_items where tbl_items.id_subcategoria = '" & ComboBox3.SelectedValue & "'"
usas el ComboBox3, esta correcto esto? no deberia ser el combobox4
ademas porque no usas parametros, no es bueno concatener el string para armar la query
saludos
gracias Leandro respecto al combobox es una cuestion asi combo 5 esta bindeado con tabla categorias y este llena al combo 3 con subcategoria siempre por select verdad y este llena al 4 cmo ves el codigo del 4 es para llenar los textbox con unidad de medida lo hace bien pero pasa esto:
ResponderEliminar1- si selecciono un item me lo muestar en textbox si selecciono un segundo no cambia nada en el text queda lo mismo que cuando seleccione el item 1 osea no actualiza el cambio......graciasssss
ahora otra pregunta con la conexion:
ResponderEliminar1 si yo tengo una aplicacion que necesito que conecte la pc1 (de forma local) a la base de datos y esta misma aplicacion la instalo en otra para que se conecte por red a la base de la pc1 puedo hacerlo todo esto con sql 2008 express edition? se que para express puedo con la .\SQLExpress en la conexion, pero desde la otra pc como seria el punto de la pregunta es saber si lo puedo haceren express....gracias Leandrooooo
ahora Leandro recuerdas que te comente que al correr una aplicacion en otra pc me da error quisiera saber como adjuntarte una foto de lo que me sale pero no se como talvez me puedes decir para que me des luz con eso que ya me tiene harto ya termine mi aplicacion y no la puedo implementar aun por eso.....gracias Leandro
ResponderEliminarhola MIND CORRUPTER
ResponderEliminardesde sql server express puede conectarte remoto, es mas habia mencionado un link que explciaba del tema:
Enable Remote Connection on SQL Server 2008 Express
solo reemplazarias el .\SQLEXPRESS por NombrePc\SQLEXPRESS
saludos
hola MIND CORRUPTER
ResponderEliminarcreo que seria recomendable seguir estos temas en el foro
visual c# foro
alli si puede publicar imagenes y se podria ahcer mas extendas la interaccion
saludos
hola Leandro como stas ..... tengo un from de compras en el hay un combo con los proveedores y a la par un boton que abre el form para crear proveedor, lo que no logro hacer es que despues de crear un proveedor se me actualize el combo de proveedores al cerrar el from de creación solo aparece el nuevo registro cuando vuelvo a abrir el from de compras........gracias de antemano
ResponderEliminarhola MIND CORRUPTER
ResponderEliminarimagino que el form para dar de alta un proveedor lo hacer de forma modal
por lo tanto al cierre dee ese form podrias recargar el combo
como se plantea aqui
http://social.msdn.microsoft.com/Forums/es-ES/vcses/thread/4f2053e5-a7f0-49cd-8eae-53df7ddfc345
en tu caso usarias
if(frm2.ShowDialog() == DialogResult.Ok){
'aqui recarga el combo
}
saludos
hola leandro tengo una duda puedo cambiarle nombre a mi instancia de SQL Server 2008 Enterprise sin que me de ningun problema despues al querer loguearme en SQL management Studio o a una conexion de vb.net? es que en mi maquina se llama de una manera y en el trabajo tiene la predeterminada MSSQLServer entonces es tedioso estar cambiando cadenas de conexion en el proyecto para cuestion de pruebas y mas que los reportes Crystal se usas con dataset y trae la cadena de mi casa no la del trabajo.......gracias de antemano
ResponderEliminarhola MIND CORRUPTER
ResponderEliminares que no deberias tener este problema si la cadena de conexion se define en un archivo de configuracion
es mas los dataset tipados crean de forma automatica esta key en el .config para cambiarla sin tener que recompilar
Archivos de Configuración - Una introducción (1/3)
saludos
gracias leandro, tengo una inquietud en mi tbl_inventario se almacenan las compras de mo form compras como sabes si hago dos compras el mismo dia del mismo item apareceran reflejadas como dualidad verdad solo que varia la cantidad, lo que quiero es sobre escribir esa dualidad en otra tabla tbl_entradas donde el mismo item tenga sumado las dos cantidades en una solaen vb.net y sql server para hacer y guardar los descargos en tbl_descargos tratando la tbl_entradas.... gracias
ResponderEliminarhola MIND CORRUPTER
ResponderEliminarpro no creo que sea correcto esto que planteas porque si bien se realzian el mismo dia son dos compras separadas
o sea el encabezado de la Orden de compra sera diferente para cada pedido por ams que sea el mismo material
la orden de compra es como la de la factura con un encabezado y un detalle
ademas no se si defines proveedores pero una oerden de compra podria aplicar a diferentes proveedores que se dispongan sobre el mismo producto, por lo tanto sumarlo no creo que sea correcto
saludos
gracias Leandro, lo que quiero plantearte es esto:
ResponderEliminarquiero mostrar las entradas pero a nivel de existencias no de ordenes ok, planteaba lo de sobreescribir porque a la hora de hacer descargo de x producto no puedo descargar sobre dos registros del mismo material por ejemplo si compre un lapiz y despues compro 2 del mismo lapiz tendria que tener 3 existencias y tratar ese registro con cantidad 3
o no se si me puedes orientar mejor con el sistema de cardex, pues hago compras y el detalle los envia a una tbl inventario, y en otra tbl entradas son los mismos registros de tbl inventario pero ordenados y unificados sin dualidades si hice tres compras del mismo material que en tbl entradas me apareca item x cantidad = 3 ya unificado pues esos registros editaria a la hora de descargar ayudame porfavor.....gracias
ResponderEliminarhola MIND CORRUPTER
ResponderEliminaren ese caso lo que queda hacer son dos queries
- una preguntando si en la tabla de inventario que existe un registro para el articulo con id=X
- si existe entonces realziar un INSERT en la tabla para ese articulo
- sino existe realizarias un UPDATE filtrando en el WHERE por ese articulo
con eso actualizarias la cantidad
UPDATE tbinventario SET stock = stock + @cant WHERE idarticulo = @idarticulo
saludos
Leandro gacias ahora sigo con dudad de conexion por red de vb.net a sql server express mi cadena de conexion en vb.net como remoto es
ResponderEliminarData Source=192.168.1.16\SQLEXPRESS;Network Library=DBMSSOCN;Initial Catalog=OVISA_DB;Integrated Security=true
ya probe tambien con el user id y password pero no obtengo resultados y otra cosa como configuro la cadena de conexion en la configuracion de my project porque no se como hacerlo gracias
hola MIND CORRUPTER
ResponderEliminarrecuerda validar que puedas conectarte de forma remota al sql express, por defecto solo permite conexiones locales
Enable Remote Connection on SQL Server 2008 Express
valida tambien que el firewall de windows no esta bloqueando la conexion
Para definir la conexion usa un archivo de configuracion
Archivos de Configuración - Una introducción (1/3)
saludos
que hay leandro oye estava checando tus publicaciones y la verdad me intereso muchisimo el como explicas y pues tengo un problema que investigo y no se me aclara tal problema.. soy principiante pero aun asi busco la manera de aprender todo esto de la programacion mi problema es el siguiente espero me lo entiendas estoy haciendo un sistema con conexion a base de datos Sql server 2008 y utilizo Visual basic, el sistema trata de un inventario de equipos de computo y sus usuarios...Tengo mis tabla USUARIO, EQUIPO DE COMPUTO, AREA(del usuario ) SOFTWARE..todos con su campo para un Id pero el punto es que al momento de insertar los datos en mi form de todos mis texbox, solo coloque uno para insertar el id del usuario pues deseo que ese id tambien se inserte en las demas tablas del como AREA, SOFTWARE etc.. ya que por logica no puedo insertar datos si los ID no pueden estar nulls y en el form se veria confuso con varios texbox para insertar los id de cada una de las otras tablas( un id para todas las tablas apartir de una tabla) mira este es parte de mi codigo el primero es de el usuario y segundo es del area
ResponderEliminarespero me ayudes por favor
Public Sub guardarusuario()
ConexionSqlServer()
Try
If ConnSql.State = ConnectionState.Closed Then
ConnSql.Open()
End If
SQLCON = "INSERT INTO USUARIO (id_usuario, nombre, cuenta_usuario, email) VALUES ('" & Me.txtusu.Text & "','" & Me.txtnombre.Text & "','" & Me.txtusua.Text & "','" & Me.txtemail.Text & "')"
cmdsql = New SqlCommand(SQLCON, ConnSql)
cmdsql.ExecuteNonQuery()
CerrarSqlServer()
Catch ex As Exception
MessageBox.Show("Error al Insertar un dato de el usuario")
End Try
End Sub
Public Sub guardarArea()
ConexionSqlServer()
Try
If ConnSql.State = ConnectionState.Closed Then
ConnSql.Open()
End If
SQLCON = "INSERT INTO AREA (area)VALUES('" & Me.TextBox1.Text & "')"
cmdsql = New SqlCommand(SQLCON, ConnSql)
cmdsql.ExecuteNonQuery()
CerrarSqlServer()
Catch ex As Exception
MessageBox.Show("Error al Insertar un dato en el area")
End Try
End Sub
espero tu respuesta pronto
ResponderEliminarhola Luis
ResponderEliminarme genera ruido esto que comentas "un id para todas las tablas apartir de una tabla", como seria esto ? porque la verdad lo veo algo raro
la idea de los id es que de ser posible sean del tipo identity, o sea la propia tabla los generes cuando se inserta
Ejemplos simples – Campos Auto numéricos (Identity)
de ser posible sua de esta forma los id de las tablas
ademas si has revisado los ejemplos de este blog, dino cuando armo una query concatenendo un string para asignar los datos
usa parametros no concatenes un string
saludos
Hola Leandro gracias por tu respuesta y si tienes razon tambien hice una tabla llamada REGISTROS la cual su ID es de tipo IDENTYTY esta tabla contiene todos los id de las demas tablas de echo el identiti me genera un auto ID con esta consula en SQL :select MAX(id_registro)+1 from REGISTRO.. asi es como dice que las genere para las demas tablas... checare los ejemplos cualkier duda te are saber gracias
ResponderEliminartengo una duda, estoy trabajando con algo similar a lo que expones en tu entrada, tengo tres form, uno es el padre y los otros dos hijos los cuales al precionar el boton para acceder a los dos form hijos se abren en un panel del form padre por lo tanto ambos quedan al descubierto, mi problema es que deseo guardar datos del form hijo y del padre en este ultimo form.t agradeceria si pudieras ayudarme =)
ResponderEliminarhola Erika
ResponderEliminarno entendi lo del panel del form padre, te refieres a que es un ambiente MDI, o sea el form padres es un mdi container?
podrias ahcer que el form hijo guarde sus datos y al final envie una accion al forma padre para que este guarde los suyos, para el usuario sera la misma operacion, pero en realidad se invocaron los metodos del form donde corresponde
saludos
Hola Leandro, me gusta mucho como explicas y confieso que tus blogs son unos de los pocos que me sirven de ayuda cuando estoy en aprietos.
ResponderEliminarSoy estudiante de informatica, pero en realidad soy principiante y me gusta mucho esto de la programaciòn. Tengo un pequeño problema el cual es el siguiente:
tengo un formulario con un dataGridView, realizo una consulta para visualizar todos los productos de una tabla que cumpla cierto criterio, eso lla me funciona, pero el problema es que ahora necesito realizar una especie de formulario detalle parecido a ese que explicas, pero a diferencia los datos se tienen que mostrar en controles como text box, pictureBox, etc. y eso es lo que no puedo hacer.
Te agradeceria mucho que me ayudaras en esto.
Esta es una pequeña parte del codigo, para que tengas un idea de los que quiero hacer:
private void pARADAMASToolStripMenuItem_Click(object sender, EventArgs e)
{
subCategoria = "Ropas para damas";
CATEGORIA_PRODUCTO();
}
private void CATEGORIA_PRODUCTO()
{ string subCategoria;
private string Departamento = "";
OleDbConnection cnx1 = new OleDbConnection(@"provider= Microsoft.Jet.OLEDb.4.0; Data Source =C:\\Servicio al cliente1.mdb");
cnx1.Open();
OleDbCommand comm1 = new OleDbCommand("SELECT Nombre_Producto, Categoria_Producto, Marca_Producto, Sub_Categoria1 FROM tbl_Productos Where sub_categoria1=@sub_categoria1", cnx1);
comm1.Parameters.AddWithValue("@sub_categoria1", subCategoria);
OleDbDataAdapter da2 = new OleDbDataAdapter(comm1);
DataTable dt = new DataTable();
da2.Fill(dt);
dataGridView1.DataSource = dt;
cnx1.Close();
}
lo que necesito es que al dar clic sobre una de los registros me llame a otro formulario con todos los detalles que quiera de este registro, pero en controles como text box y picture box ara las fotos, que no sea en otro greedView como explicaste anteriormente.
hola Alejandra
ResponderEliminarapuntas a algo como esto
[WinForms] Edición Empleados
como veras alli se lista en un datagridview pero se edita en controles simples
se pasa el id de la entidad que se quiere editar y se recupera solo ese registro para cargar los controles
saludos
Hola de Nuevo Leandro,
ResponderEliminarMuchas gracias por responderme, por lo que he visto hasta ahora es justamente lo que necesitaba, ahora intentare adaptar este ejemplo a mi proyecto.
Hasta la Próxima!!!!
Hola Leandro, una pregunta, en el caso por ejemplo, tengo un winform que controla el acceso a la aplicación, como puedo hacer para que al ingresar el usuario, código (y validar los campos) desplegar un nuevo winform pero tambien cerrando el de loggeo? tendria que se siempre con la sentencia "Me.close()" o de usar esa sentencia estaria cerrando el form que recien he abierto?
ResponderEliminarhola Bianconeri
ResponderEliminarel tema es que el login no deberias hacerlo mostrando un form desde otro
sino que lo implementas desde el Main()
Login – Usando Password con Hash
analiza el articulo alli explico como hacerlo
saludos
hola, muy interesante lo que publicas, ahora yo tengo un frm padre donde debor realizar una busqueda y que el resultado de dicha busqueda me aparezca en otro formulario en un gridview... el tema es q no se como direccionar esa la informacion a el otro formulario. estoy trabajando con .net ..te agradeceria mucho si me orientas...saludos
ResponderEliminarhola karunchi
ResponderEliminares un desarrollo winforms el que estas realizando? porque el gridview es un control de asp.net
para pasar datos al form hijo usarias
[WinForms] – Pasaje de información formulario hijo
saludos
hola leandro una consulta veraz tengo un formulario donde tengo un datagrid y ese se actualiza solo con datos al momento de cargarlo y debajo de este tengo un boton de nuevo el lo que hace es que abre un nuevo formulario modal en elcual tengo los campos y al dar click en el boton de guardar datos los inserta perfecto pero el problema que tengo es que no quiero cerrar ese formulario para capturar mas pero al hacerlo quiero que el datgrigwiew se actualice,por favor te lo agradeceria si pudieras ayudarme
ResponderEliminarhola Pablinho
ResponderEliminaren ese caso deberias analizar este otro articulo
Comunicar formularios de forma desacoplada
veras que puedes por medio de una interfaz desacoplar la comunicacion del form hijo con su padre he invocar acciones en este ultimo
podrias al guardar llamar al metodo que implementar el form padre por medio de la interfaz y recargar el grid
saludos
Hola Leandro, estos últimos días he intentado lo siguiente:
ResponderEliminarTengo un form Padre "Menú Principal", dónde mediante un ToolStripMenú llamo al form Hijo "Registro Encuestados", entonces desde el form hijo "RE", tengo un boton Nuevo, dónde abre otro form, pero simplemente con la función show(),para poder mandar datos de un datagridview a los TextBox que tengo en el formulario hijo, he ahi mi duda, intenté tus metodos con formularios MDI, pero no funciona, será debido a que desde el form hijo, estoy llamando a un form con la función show()? en ese caso que podría hacer?... Espero me puedas ayudar. Gracias de antemano.
hola Miguel
ResponderEliminarpero esos forms que mencionas los estas abriendo de forma integrada con MDI, o sea asignas la propiedad MDIParent antes de hacer el Show()?
cuando implementas la tecnica en que paete notas que no funciona?
saludos
Hola Leandro,
ResponderEliminarPues verás si estoy empleando el MDI, mi form "Menú Principal" es el padre osea le asigno a la propiedad "isMdiContainer=true", y desde ese form llamo a otro formulario "X" con un boton del ToolStripMenu, y claro antes del .show le declare el mdiparent = mi form "menú principal".
Lo que pretendía hacer es que desde el formulario hijo "X" llame a otro form con un Button dónde este form me cargará datos a un datagridview y esos datos enviarlos al formulario X.
Soy nuevo en esto de MDI, y no sé si estoy haciendo bien el llamar desde mi formulario hijo X con el metodo .show, ¿Será ese el problema?, en realidad no lo sé y no he podido encontrarle la respuesta. Por cierto gracias por responder y espero puedas ayudarme... Gracias.
hola Miguel
ResponderEliminarpero entonces por lo que explicas no estas usando la tecnica de este articulo sino que usas la de este otro:
Comunicar formularios MDI
o sea pasas datos del forma hijo a su padre, por lo que deberias conocer su instancia para poder pasarle los datos
saludos
Hola Leandro,
ResponderEliminarPase y revisé el link que me pasaste y yo buscaba todo lo contrario es decir, buscaba algo parecido a Moisés Banegas comento:
"El principal es MDI, y se llama al Form1, en form 1 tengo cajas de texto y listbox(a diferencia de un datagridview) , desde este form se llama al form2 que tengo un datagridview que lo cargo desde la BD con datos varios, lo que quiero es seleccionar varias filas del grid de Form2, y al presionar un boton del form2, este envie los datos de las filas seleccionadas al form1, de ahi yo trabajaria con los datos del form1"... La diferencia sería que yo uso TextBox y ListBox en mi form1. Él subió una solución pero para pasar los datos del datagridview del form2 al datagridview del form1. Me lo descargue para poder adaptarlo a lo que yo estoy buscando(Pasar datos de la fila seleccioanda del datagridview del form2 a TextBox y ListBox del form1 que lo invoca) sin éxito.
Este es el código adaptado que use para intentarlo:
--Form Principal--
Private Sub DdToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles DdToolStripMenuItem.Click
Dim frm As New Form1
frm.MdiParent = Me
frm.Show()
End Sub
--Form1(Formulario hijo)--
Implements AgregarFila
Public Sub AgregarFilaNueva(row As DataGridViewRow) Implements agregarFila.AgregarFilaNueva
Dim nombreDistrito As String = row.Cells("nombreDistrito").Value.ToString()
Dim idDistrito As Integer = row.Cells("idDistrito").Value.ToString()
Me.txtdistrito.Text = nombreDistrito
Me.lstdistrito.SelectedValue = idDistrito
End Sub
Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
Dim _form1 As New Form2
_form1.MdiParent = Me.MdiParent
_form1.opener = CType(Me, AgregarFila)
_form1.Show()
End Sub
--Form2--
Private formOpener As AgregarFila
Public Property opener() As AgregarFila
Get
Return Me.formOpener
End Get
Set(value As AgregarFila)
formOpener = value
End Set
End Property
Public Sub New()
InitializeComponent()
End Sub
Dim strcn As String = "Server=Local\Local;database=AppAgenda;Integrated security=true "
Public Sub listarDistrito()
Dim cn As New SqlConnection(strcn)
Try
cn.Open()
Dim cmd As SqlCommand
cmd = New SqlCommand("listarDistrito")
cmd.CommandType = CommandType.StoredProcedure
cmd.Connection = cn
Dim dt As New DataTable
dt.Load(cmd.ExecuteReader)
DataGridView1.DataSource = dt
Catch ex As Exception
MsgBox(ex.Message)
Finally
cn.Close()
End Try
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
listarDistrito()
DataGridView1.AutoGenerateColumns = False
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim ContarFilasSeleccionadas As Int32 = DataGridView1.Rows.GetRowCount(DataGridViewElementStates.Selected)
If ContarFilasSeleccionadas > 0 Then
For i As Integer = 0 To ContarFilasSeleccionadas - 1
Dim row As DataGridViewRow = TryCast(Me.DataGridView1.SelectedRows(i), DataGridViewRow)
Dim parent As AgregarFila = TryCast(Me.Owner, AgregarFila)
parent.agregarFilaNueva(row)
Next
End If
Me.Close()
End Sub
--Y por último la interface--
Public Interface AgregarFila
Sub agregarFilaNueva(row As DataGridViewRow)
End Interface
Sinceramente recién que me tope con este problema, estoy viendo lo que es Interfaces, y aunque entiendo más o menos su concepto, en la práctica no lo se aplicar aún, es por eso que me base en el código de Moisés para poder adaptarlo al mio. Desde ya le agradezco su apoyo brindado y de tomarse el tiempo de contestar, sinceramente le agradezco mucho. Espero pueda ayudarme... Un abrazo.
ResponderEliminarhola Miguel
ResponderEliminarporque defines la linea
Dim _form1 As New Form2
como que si es el Form2 el que instancias ponerle de nombre _form1 causa algunas confusiones
saludos
hola Miguel
ResponderEliminarsi usas la propiedad "opener" porque despues haces:
Dim parent As AgregarFila = TryCast(Me.Owner, AgregarFila)
no deberia ser:
Dim parent As AgregarFila = TryCast(Me.opener, AgregarFila)
aunque lo ideal seria no acopar los forms con sus nombre sino utilizar interfaces
saludos
Hola Leandro,
ResponderEliminarHice los cambios que me dijiste pero sigue el form1 sigue sin recibir los datos...
Yo uso esto:
Public Sub AgregarFilaNueva(row As DataGridViewRow) Implements AgregarFila.agregarFilaNueva
Dim nombreDistrito As String = row.Cells("nombreDistrito").Value.ToString()
Dim idDistrito As Integer = row.Cells("idDistrito").Value.ToString()
Me.txtdistrito.Text = nombreDistrito
Me.lstdistrito.SelectedValue = idDistrito
End Sub
Mientras que en el ejemplo de Moisés usa esto:
public void AgregarFilaNueva(DataGridViewRow row)
{
string item = row.Cells["item"].Value.ToString();
string desc = row.Cells["Desc"].Value.ToString();
this.dgvDetalleFactsAbono.Rows.Add(new []{ item, desc });
}
Es posible que este definiendo mal la recepción de datos?, o en todo caso como es que puedo recepcionar los datos del datagridview del form2 en mi TextBox y ListBox del form1?.
hola Miguel
ResponderEliminarsi pones un breakpoint en el metodo AgregarFilaNueva() puedes validar pasa por alli la ejecucion ?
porque quizas el problema sea que no se puede resolver la instancia del form que se invoca desde el form2
saludos
HOLA LEANDRO TENGO UN PROBLEMITA
ResponderEliminarTENGO UN PROYECTO DONDE LO E INCOPORADO DENTRO DE OTRO PROYECTO PERO LO QUE DESEO ES QUE MEDIANTE UN BOTON ME LLAME AL FORMULARIO DE OTRO PROYECTO PORFA ES EN C#
hola jose
ResponderEliminarese otro proyecto es una aplicacion que tu estas desarrollando? o es de terceros
lo planteo porque de forma simpel no se puede realizar lo que quieres conseguir, podrias desde .net lanzar una aplicacion cmo ser un .exe usando el
Process.Start()
pero no podrias indicar que se abra determinado formulario salvo que esa aplicacion acepte algun comando como argumento y que lo pueda intepretar para saber que forma mostrar
por eso decia si la aplicacion eres tu quien la desarrolla podrias poner ese parametro para invocar el .exe y decirle por linea de comando que forma debe mostrar
saludos
Hola Leandro, los links de descargas para estos ejemplos al parecer estan deshabilitados. los puedes habilitar??
ResponderEliminarSaludos
hola MatiCris
ResponderEliminarya estan actualizadon los links
saludos
hola leandro
ResponderEliminarsera que puedas poner un ejemplo de como multiplicar un la cantidad que se ingresa en un txtbox con un columna del datagridview en c# por favor!!!!!!!
saludo espero que me puedad ayudar!!!!
saludos!!!!!!
hola ROUSANYE
ResponderEliminarno entendi un textbox con una columna?
pero la columna tiene varias rows como seria eso de la multimplicacion ?
dodne verias el resultado, en otro columna, en un textbox?
saludos
ola leandro
ResponderEliminarmira quiero multiplicar los datos de un from por medio un texbo--aqui se introduce la cantidad con una columna de datagridview que es precio? y mostrarlo en otro from actualizado ejempo
el precio de una hamburguesa(25.00) * (2)(son las cantidad que el cliente desea) y cuando haga la operacion me lo mande al otro formulario
actualizando el precio sera que me puedad ayudar?
hola ROUSANYE
ResponderEliminarlo que no me queda claro es como se comunican los formularios, si es un form padre que envia datos al form hijo o al contrario
lo planteo porque la forma de comunicar los forms cambia segun el caso
si tienes que pasar varios datos de un forma a otro recomendaria vuelques los mismos en alguna lista y esa la pases, asi no acoplas los forms pasando controles entre ellos
saludos
Muchas gracias por brindar el Código Fuente felicitaciones!
ResponderEliminarHola Leandro.
ResponderEliminares una aplicación MDI. tengo un Formulario padre, el cual manda llamar a un hijo que realiza captura y actualización de datos, en cierto momento mando llamar a un tercer formulario que muestra informacion ya existente, la cual sera agregada a la nueva captura, esto con el fin de ahorrar pasos, el caso es que desde el primero hijo quiero invocar la función guardar del hijo 3 pasando un parámetro, pero me arroja el siguiente mensaje de error.
Unable to cast object of type 'VFCRequisicion.MenuVFCRequisicion' to type 'VFCRequisicion.Requisicion.FrmHeaderDetalleOrdenCorteReasigna'.
El llamado lo hago de la siguiente manera
FrmRequisicionOrdenCorte FrmOrdenCorte = new FrmRequisicionOrdenCorte();
NoRequisicionReasigna = NoRequisicionValor;
NoRequisicionValor = FrmRequisicionOrdenCorte.NoRequisicionValor;
((FrmHeaderDetalleOrdenCorteReasigna)this.MdiParent).GuardarDatos(NoRequisicionValor);
FrmOrdenCorte.MdiParent = this.MdiParent;
FrmOrdenCorte.Show();
this.Close();
donde FrmRequisicionOrdenCorte es el hijo 3 y es donde me arroja el erro.
de antemano gracias por el apoyo
Buen dia inge.
ResponderEliminarTengo un formulario de busqueda de un dato (Registro de una Tabla) al hacer click en un boton me debe mostrar un mensaje de que no encontró el dato ingresado, de lo contrario si lo encuentra una imagen y la informacion del dato.
podria servirme el ejemplo 1 o el 2, (Teniendo en cuenta que lo que quisiera hacer es asociar el dato buscado a una imagen que se repetira en varios registros y que al momento de que de click en la imagen muestre la informacion en un datagridview).
saludos y feliz año nuevo
¿Qué tal? Buen día. Probé para mi código la primer opción y sí pasa el dato, pero de alguna manera no me muestra el valor en el campo de texto. En mi caso, lo estoy pasando desde un Control DevExpress.XtraEditors.XtraUserControl a un formulario simple. He cambiado el Modifiers de ambos lados pero ni así me muestra, ¿qué crees que pueda ser? ¡Saludos y gracias!
ResponderEliminar