martes, 17 de mayo de 2016

Windows Forms. Pasar datos entre formularios

El código completo tanto en C# como en Visual Basic .NET está disponible en:

Códigos de muestra - Ejemplos MSDN. Comunicación entre formularios Windows Forms

Esta es una consulta muy habitual: ¿Cómo pasar datos entre dos formularios?

Evidentemente hay múltiples formas de hacerlo y elegir la mejor depende en gran medida del caso particular. En este artículo mostraré un ejemplo de cómo podemos solucionar uno de los escenarios más repetidos y que puede ajustarse a muchos de los escenarios que se plantean habitualmente: crear un formulario para editar los datos de una fila de un DataGridView.

Para mostrar el ejemplo voy a crear un nuevo proyecto Windows Forms llamado DialogForm en el que definiré dos formularios:

Un formulario principal llamado MainForm que tendrá un control DataGridView (dataGridView1) para mostrar los datos y un botón (btnAdd) para añadir nuevas filas.

En el DataGridView definiré 4 columnas: dos de tipo DataGridViewTextBoxColumn para el Nombre (NameColumn) y Apellido (SurnameColumn), una de tipo DataGridViewCheckboxColumn para indicar si el registro está Activo (ActiveColumn) y una de tipo DataGridViewButtonColumn (EditColumn) que contendrá el botón para llamar al formulario de edición.

Por último, ya que la edición de los registros se realizará a través de un formulario, deshabilitaré las propiedades que permiten añadir, eliminar y eliminar filas en el DataGridView.

Formulario principal

Un segundo formulario (DialogForm) para editar los datos de las filas. Este segundo formulario tendrá dos TextBox (txtName y txtSurname) con sus respectivas etiquetas para el nombre y apellido, un CheckBox (chkActive) para indicar si el registro está activo, y dos botones (btnOk y btnCancel) para confirmar o cancelar la edición.

Formulario de edición

Para acabar de preparar el ejemplo voy a crear una clase Person para encapsular los datos de cada una de las filas. Esta clase tendrá dos propiedades Name y Surname de tipo String y una propiedad Active de tipo Boolean.


    internal class Person
    {

        public string Name { get; set; }

        public string Surname { get; set; }

        public  bool Active { get; set; }

    }
Friend Class Person

    Public Property Name As String

    Public Property Surname As String

    Public Property Active As Boolean

End Class

El formulario de edición

El código del formulario de edición es extremadamente simple.

En primer lugar voy a crear una propiedad interna CurrentPerson de tipo Person que permitirá establecer y leer los valores del formulario desde el resto de las clases del proyecto. El método get de esta propiedad devuelve un objeto Person con los datos introducidos en el formulario, mientras que el método set recibe un objeto Person y rellena con los datos recibidos los controles del formulario:


        internal Person CurentPerson
        {
            get
            {
                return new Person()
                {
                    Name= txtName.Text,
                    Surname = txtSurname.Text,
                    Active = chkActive.Checked
                };
            }
            set
            {
                txtName.Text = value == null ? string.Empty : value.Name;
                txtSurname.Text = value == null ? string.Empty : value.Surname;
                chkActive.Checked = value != null && value.Active;
            }
        }
    Friend Property CurrentPerson As Person
        Get
            Return New Person() With
            {
                .Name=txtName.Text,
                .Surname=txtSurname.Text,
                .Active=chkActive.Checked
            }
        End Get
        Set
            txtName.Text = If(Value Is Nothing, String.Empty, Value.Name)
            txtSurname.Text = If(Value Is Nothing, String.Empty, Value.Surname)
            chkActive.Checked = Value IsNot Nothing AndAlso value.Active
        End Set
    End Property

Los botones simplemente se encargarán de establecer el valor de la propiedad DialogResult del formulario. El botón Aceptar establece un valor de DialogResult.OK mientras que el botón Cancelar establecerá el valor DialogResult.Cancel.


        private void btnOk_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.OK;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.Cancel;
        }
    Private Sub btnOk_Click(sender As Object, e As EventArgs) Handles btnOk.Click
        DialogResult = DialogResult.OK
    End Sub

    Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
        DialogResult = DialogResult.Cancel
    End Sub




El formulario principal

En el formulario principal voy a cargar algunos datos de prueba en el evento Load del formulario:


        private void MainForm_Load(object sender, EventArgs e)
        {
            dataGridView1.Rows.Add("Darth", "Vader", true);
            dataGridView1.Rows.Add("Luke", "Skywalker", false);
            dataGridView1.Rows.Add("Leia", "Organa", true);
            dataGridView1.Rows.Add("Han", "Solo", false);
            dataGridView1.Rows.Add("Obi-Wan", "Kenobi", true);
            dataGridView1.Rows.Add("Wilhuff", "Tarkin", false);
        }
    Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        dataGridView1.Rows.Add("Darth", "Vader", True)
        dataGridView1.Rows.Add("Luke", "Skywalker", False)
        dataGridView1.Rows.Add("Leia", "Organa", True)
        dataGridView1.Rows.Add("Han", "Solo", False)
        dataGridView1.Rows.Add("Obi-Wan", "Kenobi", True)
        dataGridView1.Rows.Add("Wilhuff", "Tarkin", False)
    End Sub

Para editar una fila al pulsar el botón Editar de la fila introduciremos el código en el evento ContentClick del grid. Al pulsar el botón crearé una nueva instancia del formulario DialogForm estableciendo como valor de la propiedad CurrentPerson un objeto Person con los datos de la fila.
A continuación mostraré el diálogo utilizando el método ShowDialog. Si este método devuelve un valor DialogResult.OK recupero los valores actuales de la propiedad CurrentPerson que devolverá los valores actuales de los controles del formulario de edición y los establezco como valores de la fila:


        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            var grid = (DataGridView) sender;
            if (grid.Columns[e.ColumnIndex].Name != "EditColumn") return;

            var rowToEdit = grid.Rows[e.RowIndex];
            var dialog = new DialogForm
            {
                CurentPerson = new Person()
                {
                    Name = (string) rowToEdit.Cells["NameColumn"].Value,
                    Surname = (string) rowToEdit.Cells["SurnameColumn"].Value,
                    Active = (bool) rowToEdit.Cells["ActiveColumn"].Value
                }
            };

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                rowToEdit.Cells["NameColumn"].Value = dialog.CurentPerson.Name;
                rowToEdit.Cells["SurnameColumn"].Value = dialog.CurentPerson.Surname;
                rowToEdit.Cells["ActiveColumn"].Value = dialog.CurentPerson.Active;
            }
        }
    Private Sub dataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles dataGridView1.CellContentClick
        Dim grid = CType(sender, DataGridView)
        If grid.Columns(e.ColumnIndex).Name <> "EditColumn" Then
            Return
        End If

        Dim rowToEdit = grid.Rows(e.RowIndex)
        Dim dialog = New DialogForm() With
        {
            .CurrentPerson = New Person() With
            {
                .Name = rowToEdit.Cells("NameColumn").Value,
                .Surname = rowToEdit.Cells("SurnameColumn").Value,
                .Active = rowToEdit.Cells("ActiveColumn").Value
            } 
        }

        If dialog.ShowDialog() = DialogResult.OK Then
            rowToEdit.Cells("NameColumn").Value = dialog.CurrentPerson.Name
            rowToEdit.Cells("SurnameColumn").Value = dialog.CurrentPerson.Surname
            rowToEdit.Cells("ActiveColumn").Value = dialog.CurrentPerson.Active
        End If
    End Sub

El código del botón Añadir es más sencillo. Simplemente creo una nueva instancia del formulario DialogForm sin establecer ningún valor en la propiedad CurrentPerson para mostrar el formulario vacío.
Si el método ShowDialog devuelve DialogResult.OK se establecen los valores de la propiedad CurrentPerson como valores de las celdas de una nueva fila del DataGridView.


        private void btnAdd_Click(object sender, EventArgs e)
        {
            var dialog = new DialogForm();
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                dataGridView1.Rows.Add(
                    dialog.CurentPerson.Name,
                    dialog.CurentPerson.Surname,
                    dialog.CurentPerson.Active
                    );
            }
        }
    Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
        Dim dialog = New DialogForm()
        If dialog.ShowDialog() = DialogResult.OK Then
            dataGridView1.Rows.Add(
                dialog.CurrentPerson.Name,
                dialog.CurrentPerson.Surname,
                dialog.CurrentPerson.Active
            )
        End If
    End Sub

Si arrancamos la aplicación podemos comprobar que tanto el botón Editar como el Añadir permiten editar y añadir nuevas filas.

Formulario de edición


El código completo tanto en C# como en Visual Basic .NET está disponible en:

Códigos de muestra - Ejemplos MSDN. Comunicación entre formularios Windows Forms

8 comentarios:

  1. De gran ayuda. Muchisimas gracias!

    ResponderEliminar
  2. Gracias: Después de tanto buscar encuentras esto que te explica bien como se debe..

    ResponderEliminar
  3. tengo una duda donde puedo crear el currentPerson

    ResponderEliminar
  4. Tengo una consulta estoy realizando un proyecto para mi universidad en donde quiero pasar los datos de un datagridview de un formulario a los combobox y textbox de otro formulario... al momentos de ejecutar el codigo unicamente me captura los textbox pero los combobox no me captura los combobox. Podrias mostrar un ejemplo de como harias el codigo para que me cacture los combobox.. espero tu pronta respuesta

    ResponderEliminar
  5. Respuestas
    1. Hola tienes que leer detalladamente la explicación.. ese es el nombre del segundo formulario

      Eliminar