viernes, 22 de enero de 2010

[WinForms] – Pasaje de información formulario hijo

 

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.

  • Comunicar formularios MDI
  • Comunicar formularios de forma desacoplada
  • DataGridView – Parte 3 – Pasaje de información entre grillas en distintos formularios

    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.

  • 95 comentarios:

    1. Leandro,quisiera pedirte opinion.Estoy desaroyando una pequeña aplicacion con base de datos.
      Varios 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?.

      ResponderEliminar
    2. hola victor,
      te 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

      ResponderEliminar
    3. 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

      ResponderEliminar
    4. Hola Leandro saludos, agradeciendo tus blogs y ayudas, como siempre muy atento en realizar este tipo de tutoriales. Bonito dia
      atte:(Dacory)

      ResponderEliminar
    5. hola yoyis

      Me alegro que haya sido de utilidad

      saludos

      ResponderEliminar
    6. hola, tengo una duda con respecto al tema.
      Quiero 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!

      ResponderEliminar
    7. hola LJ

      En 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

      ResponderEliminar
    8. Hola Leandro, tengo una duda enorme y espero que me puedas ayudar.

      Tengo 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.

      ResponderEliminar
    9. hola Ivanhoe

      bueno 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

      ResponderEliminar
    10. Hola Leandro, tienes razón, es un enredadero de formularios y tampoco me gusta, jeje, vere que puedo hacer. Gracias!!

      ResponderEliminar
    11. hola 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.

      ResponderEliminar
    12. hola MIND CORRUPTER

      imagino 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

      ResponderEliminar
    13. 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.
      de antemano muchas gracias.

      ResponderEliminar
    14. hola

      si 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

      ResponderEliminar
    15. 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

      ResponderEliminar
    16. Este comentario ha sido eliminado por el autor.

      ResponderEliminar
    17. hola MIND CORRUPTER

      pero 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

      ResponderEliminar
    18. de hecho le habia agregado al boton cerrar del form que guarda los datos esta linea
      Form_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)

      ResponderEliminar
    19. 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

      ResponderEliminar
    20. hola 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....

      ResponderEliminar
    21. hola MIND CORRUPTER

      no 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

      ResponderEliminar
    22. 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
      ya me desespero este asunto.

      ResponderEliminar
    23. ya resolvi leandreo gracias simplemente no regeneraba si habian errores pero todo bien gracias....

      ResponderEliminar
    24. hola 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

      ResponderEliminar
    25. hola MIND CORRUPTER

      sino 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

      ResponderEliminar
    26. 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.

      ResponderEliminar
    27. perdon 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!!!

      ResponderEliminar
    28. ahora 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

      ResponderEliminar
    29. hola MIND CORRUPTER

      me 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

      ResponderEliminar
    30. hola MIND CORRUPTER

      en 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

      ResponderEliminar
    31. hola MIND CORRUPTER

      para 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

      ResponderEliminar
    32. 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
      los 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.........

      ResponderEliminar
    33. 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.


      no entiendo porque los muestar asi graciasssss.....

      ResponderEliminar
    34. 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

      ResponderEliminar
    35. hola MIND CORRUPTER

      para 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

      ResponderEliminar
    36. hola MIND CORRUPTER

      con 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

      ResponderEliminar
    37. hola MIND CORRUPTER

      podrias 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

      ResponderEliminar
    38. 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

      ResponderEliminar
    39. leandro que tal gracias por tu ayuda una consulta con codigo tengo este
      Private 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

      ResponderEliminar
    40. hola MIND CORRUPTER


      para 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

      ResponderEliminar
    41. hola MIND CORRUPTER

      veo 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

      ResponderEliminar
    42. 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:
      1- 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

      ResponderEliminar
    43. ahora otra pregunta con la conexion:
      1 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

      ResponderEliminar
    44. 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

      ResponderEliminar
    45. hola MIND CORRUPTER

      desde 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

      ResponderEliminar
    46. hola MIND CORRUPTER

      creo 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

      ResponderEliminar
    47. 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

      ResponderEliminar
    48. hola MIND CORRUPTER

      imagino 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

      ResponderEliminar
    49. 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

      ResponderEliminar
    50. hola MIND CORRUPTER

      es 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

      ResponderEliminar
    51. 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

      ResponderEliminar
    52. hola MIND CORRUPTER

      pro 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

      ResponderEliminar
    53. gracias Leandro, lo que quiero plantearte es esto:
      quiero 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

      ResponderEliminar
    54. 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

      ResponderEliminar
    55. hola MIND CORRUPTER

      en 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

      ResponderEliminar
    56. 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

      Data 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

      ResponderEliminar
    57. hola MIND CORRUPTER

      recuerda 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

      ResponderEliminar
    58. 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
      espero 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

      ResponderEliminar
    59. hola Luis

      me 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

      ResponderEliminar
    60. 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

      ResponderEliminar
    61. tengo 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 =)

      ResponderEliminar
    62. hola Erika

      no 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

      ResponderEliminar
    63. 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.

      Soy 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.

      ResponderEliminar

    64. 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.

      ResponderEliminar
    65. hola Alejandra

      apuntas 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

      ResponderEliminar
    66. Hola de Nuevo Leandro,

      Muchas 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!!!!

      ResponderEliminar
    67. 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?

      ResponderEliminar
    68. hola Bianconeri

      el 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

      ResponderEliminar
    69. 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

      ResponderEliminar
    70. hola karunchi

      es 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

      ResponderEliminar
    71. 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

      ResponderEliminar
    72. hola Pablinho

      en 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

      ResponderEliminar
    73. Hola Leandro, estos últimos días he intentado lo siguiente:
      Tengo 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.

      ResponderEliminar
    74. hola Miguel

      pero 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

      ResponderEliminar
    75. Hola Leandro,
      Pues 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.

      ResponderEliminar
    76. hola Miguel

      pero 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

      ResponderEliminar
    77. Hola Leandro,
      Pase 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

      ResponderEliminar
    78. 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.

      ResponderEliminar
    79. hola Miguel

      porque 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

      ResponderEliminar
    80. hola Miguel

      si 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

      ResponderEliminar
    81. Hola Leandro,
      Hice 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?.

      ResponderEliminar
    82. hola Miguel

      si 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

      ResponderEliminar
    83. HOLA LEANDRO TENGO UN PROBLEMITA
      TENGO 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#

      ResponderEliminar
    84. hola jose

      ese 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

      ResponderEliminar
    85. Hola Leandro, los links de descargas para estos ejemplos al parecer estan deshabilitados. los puedes habilitar??

      Saludos

      ResponderEliminar
    86. hola MatiCris

      ya estan actualizadon los links

      saludos

      ResponderEliminar
    87. hola leandro
      sera 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!!!!!!

      ResponderEliminar
    88. hola ROUSANYE

      no 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

      ResponderEliminar
    89. ola leandro
      mira 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?

      ResponderEliminar
    90. hola ROUSANYE

      lo 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

      ResponderEliminar
    91. Muchas gracias por brindar el Código Fuente felicitaciones!

      ResponderEliminar
    92. Hola Leandro.

      es 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

      ResponderEliminar
    93. Buen dia inge.

      Tengo 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

      ResponderEliminar
    94. ¿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