none
¿Qué evento controlar en un DataGridView?

    Pregunta

  • Tengo un DGV enlado a ADO.NET tipado, concretamente a un BindingSource, y quiero saber qué evento se produce cuando añado una fila nueva o cuando la modifico. El propio VS 2008 lo hace cambiando el icono que aparece a la izquierda de la fila. he probado varios o no doy con él.

    Un saludo.
    jueves, 4 de marzo de 2010 21:03

Respuestas

  • hola

    si la idea es espwecificar valore pode defecto a las celdas que el usuario no completa

    Cómo: Especificar valores predeterminados para nuevas filas en el control DataGridView de formularios Windows Forms

    porque no aplicas una tecnica similar a la mencionada en el link


    por otro lado en tu codigo puedo notar que no estas detectando que nombre de celda lanza el evento


    si analzias el ejemplo veras que usa

    private void dataGridView1_CellValidating(object sender,
        DataGridViewCellValidatingEventArgs e)
    {
      
        if (dataGridView1.Columns[e.ColumnIndex].Name == "CompanyName")
        {
            .
            .
        }
    }

    es importante detectar el nombre de la columna

    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    lunes, 8 de marzo de 2010 17:24
  • hola

    me imagine que era por eso que no validabas el nombre de la columna, pero ten en cuanta quen estos eventos son genericos a nivel de celda, todas las celdas de todos los campos lanzan este mismo eventos, y puede que no quieras el mismo  efecto en todas, es por eso que se controla por el nombre de la columna


    >Pero para mi sorpresa aunque el evento se dispara y el DGV me llega con la fila nueva, lo se por el >count, al salir de la fila del DGV me da una excepción de que CodAsesora no puede ser NULL

    tendrias exactamente la descripcion del error que visualizas, y en que punto.

    veo en esta linea

    dtgDietas.Rows[filaActual].Cells["CodAsesora"].Value = comun.CodAsesora;

    que asignas un valor a la celda que lleva ese nombre, pero lo que no logro entender es de donde sale "comun.CodAsesora", has validado que este objeto y propiedad tenga un valor distinto a null ?

    te en cuenta demas que el RowValidating tambien discrimina por el nombre de la columna al momento de validar

    C ó mo: Validar datos en el control DataGridView de formularios Windows Forms

    ademas la idea de la validacion no es la de asignar valores a los campos, sino la de validar que los ingresados sean correctos, segun veo no estas usando adecuadamente este evento

    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    martes, 9 de marzo de 2010 3:16

Todas las respuestas

  • hola

    basicamente los eventos de modificacion no se da a niveld e fila sino de celda

    CellBeginEdit

    CellEndEdit

    en los ejemplos de los link veras que puedes detectar la columna ques e esta editando, y la fila tambien usando los

    e.RowIndex y e.ColumnIndex

    para detectar si se agrega una nueva row podrias usar
    RowsAdded

    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    jueves, 4 de marzo de 2010 21:20
  • Hola Leandro,

    ya probé el evento RowsAdded, pero lo que quiero hacer es cargar con unos valores por defecto un par de columnas del DGV justo cuando se empieza a añadir la fila, y RowsAdded se lanza al finalizar la inserción de la DataGridViewRow. Se me había ocurrido utilizar la propiedad DefaultValue de la columna y así cuando inserta automáticamente me ofrece dicho valor, en este caso para el valor de una columna me sirve, ya que siempre es el mismo, pero para otra no, ya que depende de la elección de un combobox externo. Reviso los enlaces que me has pasado a ver si me sirven.

    Seguramente utilizarán los eventos de edición/finalización de celda y controlan si el número de fila es nuevo o no.

    Qué haríamos sin gente como tu. Gracias.
    viernes, 5 de marzo de 2010 7:44
  • hola

    pero si queires agregar valroes por defecto no uses los eventos de la grilla, usa el Form_load d eru formulario

    alli podrias agregar estos row adicionales

    - lo que no comprendi es como juega lo de la row y lo de la columna
    o sea comentas que agregas la fila, pero despeus trabajas con el valor de la columna, alli me perdi

    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    viernes, 5 de marzo de 2010 12:47
  • Hola Leandro,

    realmente lo que debo rellenar son las celdas de la fila, pero para poner por defecto en el evento Load del formulario hacía esto:

    dSDietas.Dietas.Columns[1].DefaultValue = 7777;

    Como ya te comenté esto me soluciona una de las celdas pero hay otra que es variable y he hecho que funcione así:

    private void dtgDietas_RowValidating(object sender, DataGridViewCellCancelEventArgs e)
    {
     if (dtgDietas.Rows[e.RowIndex].Cells["CodAsesora"].Value == DBNull.Value)
     {
      int filaActual = e.RowIndex;
      dtgDietas.Rows[filaActual].Cells["CodAsesora"].Value = comun.CodAsesora;
      dtgDietas.Rows[filaActual].Cells["CodDieta"].Value = 7777;
      dtgDietas.Rows[filaActual].Cells["CodGrupoDieta"].Value = codGrupo;
      dtgDietas.Rows[filaActual].Cells["Heredada"].Value = 1;
     }
    }

    En este caso lo que sucede es que cada vez que se valida una fila del DGV se lanza el evento de ahí que controle la celda de CodAsesora, ya que si esta está vacía me indica que es una nueva fila.

    La cuestión es que para evitar esto he intentado hacerlo en un evento del DataBindingSource:

    private void fKDietasGruposBindingSource_AddingNew(object sender, AddingNewEventArgs e)
    {
     MessageBox.Show("PRUEBA Binding AddNew");
     int filaActual = dtgDietas.Rows.Count-1;
     dtgDietas.Rows[filaActual].Cells["CodAsesora"].Value = comun.CodAsesora;
     dtgDietas.Rows[filaActual].Cells["CodDieta"].Value = 7777;
     dtgDietas.Rows[filaActual].Cells["CodGrupoDieta"].Value = codGrupo;
     dtgDietas.Rows[filaActual].Cells["Heredada"].Value = 1;
    }

    Pero para mi sorpresa aunque el evento se dispara y el DGV me llega con la fila nueva, lo se por el count, al salir de la fila del DGV me da una excepción de que CodAsesora no puede ser NULL.
    ¿Se te ocurre alguna forma de solucuionarlo?

    Una vez más mil gracias.
    lunes, 8 de marzo de 2010 16:18
  • hola

    si la idea es espwecificar valore pode defecto a las celdas que el usuario no completa

    Cómo: Especificar valores predeterminados para nuevas filas en el control DataGridView de formularios Windows Forms

    porque no aplicas una tecnica similar a la mencionada en el link


    por otro lado en tu codigo puedo notar que no estas detectando que nombre de celda lanza el evento


    si analzias el ejemplo veras que usa

    private void dataGridView1_CellValidating(object sender,
        DataGridViewCellValidatingEventArgs e)
    {
      
        if (dataGridView1.Columns[e.ColumnIndex].Name == "CompanyName")
        {
            .
            .
        }
    }

    es importante detectar el nombre de la columna

    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    lunes, 8 de marzo de 2010 17:24
  • Como se trata de un evento de validación de una fila yo hacía directamente:

     if (dtgDietas.Rows[e.RowIndex].Cells["CodAsesora"].Value == DBNull.Value)

    cuando el valor es null se que es una nueva fila, pero si es mejor controlar el nombre de la columna lo hago.

    Y con respecto a esta duda:

    Pero para mi sorpresa aunque el evento se dispara y el DGV me llega con la fila nueva, lo se por el count, al salir de la fila del DGV me da una excepción de que CodAsesora no puede ser NULL.

    ¿Se te ocurre alguna forma de solucuionarlo?

    Saludos.

    lunes, 8 de marzo de 2010 17:33
  • hola

    me imagine que era por eso que no validabas el nombre de la columna, pero ten en cuanta quen estos eventos son genericos a nivel de celda, todas las celdas de todos los campos lanzan este mismo eventos, y puede que no quieras el mismo  efecto en todas, es por eso que se controla por el nombre de la columna


    >Pero para mi sorpresa aunque el evento se dispara y el DGV me llega con la fila nueva, lo se por el >count, al salir de la fila del DGV me da una excepción de que CodAsesora no puede ser NULL

    tendrias exactamente la descripcion del error que visualizas, y en que punto.

    veo en esta linea

    dtgDietas.Rows[filaActual].Cells["CodAsesora"].Value = comun.CodAsesora;

    que asignas un valor a la celda que lleva ese nombre, pero lo que no logro entender es de donde sale "comun.CodAsesora", has validado que este objeto y propiedad tenga un valor distinto a null ?

    te en cuenta demas que el RowValidating tambien discrimina por el nombre de la columna al momento de validar

    C ó mo: Validar datos en el control DataGridView de formularios Windows Forms

    ademas la idea de la validacion no es la de asignar valores a los campos, sino la de validar que los ingresados sean correctos, segun veo no estas usando adecuadamente este evento

    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    martes, 9 de marzo de 2010 3:16
  • Hola Leandro,

    "comun.CodAsesora" es una variable declarada como Public Static en una clase llamada comun, estoy seguro al 100% que llega el código bueno.

    Por otra parte, entiendo que el evento que utilizo, RowValidating, no es el más correcto así que he cambiado a RowsAdded ya que el otro que me interesaba,  no me funciona.

            private void fKDietasGruposBindingSource_AddingNew(object sender, AddingNewEventArgs e)
            {
                int filaActual = dtgDietas.Rows.Count - 1;
                int codGrupo = Convert.ToInt32(cmbCodGrupo.SelectedValue);
                // Recupera último código de dieta.
                var q = (from p in dSDietas.Dietas
                         where p.CodGrupo == codGrupo
                         select p.CodDieta).Max();
                int nuevoCodDieta = q + 1;
                dtgDietas.Rows[filaActual].Cells["CodAsesora"].Value = comun.CodAsesora;
                dtgDietas.Rows[filaActual].Cells["CodDieta"].Value = nuevoCodDieta;
                dtgDietas.Rows[filaActual].Cells["CodGrupoDieta"].Value = codGrupo;
                dtgDietas.Rows[filaActual].Cells["Heredada"].Value = 1;
                PresentarVisitas();
            }
      
      private void PresentarVisitas()
            {
                foreach (DataGridViewRow miDgv in dtgDietas.Rows)
                {
                    MessageBox.Show(miDgv.Cells["CodAsesora"].Value.ToString() + " " + miDgv.Cells["CodDieta"].Value.ToString());
                }
            }

      private void dtgDietas_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
            {
                PresentarVisitas();
      }

    He hecho una ejecución paso a paso y veo que al situarme en la fila vacía del DGV lo primero que se lanza es el evento AddingNew del BindingSource , de este el DGV sale correctamente cargado (lo compruebo en PresentarVisitas(), después se lanza el evento  RowsAdded y aquí ya no llega la fila que he añadido anteriormente al DGV. La colección Rows del DGV llega con una fila más y la que creé antes ha desaparecido.

    Saludos.
    martes, 9 de marzo de 2010 10:25
  • Ahora al dejar como evento para introducir las celdas a RowsAdded, me sucede que al grabar al hacer dSDietas.Dietas.AcceptChanges(); se lanza el evento RowsAdded y me da problemas de concurrencia, ¿qué puedo hacer?.

      private void btnSaveItem_Click(object sender, EventArgs e)
            {
                if (dtgDietas.Rows[dtgDietas.CurrentRow.Index].Cells["CodAsesora"].Value == DBNull.Value)
                    dtgDietas.CancelEdit();
                else
                    dtgDietas.EndEdit();

                // Nos aseguramos que no queda ninguna modificación pendiente de confirmar.
                fKDietasGruposBindingSource.EndEdit();
                fKDietasDetallesBindingSource.EndEdit();

                // Enviamos cambios a la base de datos subyacente.
                dietasTableAdapter.Update(dSDietas.Dietas);
                dietasDetalleTableAdapter.Update(dSDietas.DietasDetalle);

                // Inicializamos estado de las filas.
                dSDietas.Dietas.AcceptChanges();
                dSDietas.DietasDetalle.AcceptChanges();
            }

    martes, 9 de marzo de 2010 11:00
  • Hola de nuevo,

    para este último problema se me ha ocurrido y funciona quitar el manejador del evento y luego volver a añadirlo:

     

    this.dtgDietas.RowsAdded -= new System.Windows.Forms.DataGridViewRowsAddedEventHandler(this.dtgDietas_RowsAdded);

    dSDietas.Dietas.AcceptChanges();

    dSDietas.DietasDetalle.AcceptChanges();

     

    this.dtgDietas.RowsAdded += new System.Windows.Forms.DataGridViewRowsAddedEventHandler(this.dtgDietas_RowsAdded);

    Me queda pendiente la duda que he planteado anteriormente.

    Saludos.

    martes, 9 de marzo de 2010 11:55
  • Hola,

    creo que la respuesta puede venir por aquí:

    http://msdn.microsoft.com/es-es/library/a127sbc5(VS.80).aspx

    http://msdn.microsoft.com/es-es/library/system.windows.forms.bindingsource.addingnew(VS.80).aspx
    http://msdn.microsoft.com/es-es/library/a127sbc5(VS.80).aspx

    y mi código sería:

    private void fKDietasGruposBindingSource_AddingNew(object sender, AddingNewEventArgs e)
    {
     DSDietas.DietasRow newDieta = dSDietas.Dietas.NewDietasRow();
     newDieta.CodAsesora = comun.CodAsesora;
     newDieta.CodDieta = NuevoCodDieta(Convert.ToInt32(cmbCodGrupo.SelectedValue));
     newDieta.Nombre = "";

     e.NewObject = newDieta;
    }

    Ahora me sucede que al hacer e.NewObject = newDieta me indica:

    "Los objetos agregados a una lista de BindingSource deben ser todos del mismo tipo."

    el problema está en que el DataSource de ese DGV es una relación de otro BindingSource.

    GruposBindingSource - fkDietasGruposBindingSource y desconozco cómo conocer que tipo de dato es e.NewObject. He probado con el método GetType() pero no me funciona.

    Saludos.

    jueves, 11 de marzo de 2010 13:55