2011-02-02 25 views
7

Hola, tengo un formulario de Windows que contiene una barra de menú, una barra de herramientas y un control DataGridView. Estoy usando VB.Net.Validar DataGridView en el elemento de menú, haga clic en

Tengo un botón para guardar en la tira de herramientas y un elemento de menú para guardar. Necesito la validación para ejecutar antes de que se produzca el guardado. Mi problema es que si se cambia un valor de celdas y se hace clic en cualquiera de los botones de guardar, la validación no se ejecuta y, por lo tanto, el nuevo valor no se guarda.

He echado un vistazo a los eventos en el DataGridView, como el evento 'dejar' sin embargo, ninguno parece hacer lo que quiero. Es decir. 'dejar' no se ejecuta cuando se hace clic en cualquiera de los botones guardar.

¿Alguien sabe de una forma en que puedo ejecutar mi código de validación cuando se hace clic en uno de estos botones (o en cualquier otro botón).

¡Cualquier ayuda es muy apreciada!

Respuesta

1

La cuestión es que al hacer clic en un botón, ya sea en un control ToolStrip o un elemento en un control MenuStrip hace no causa los Validating/Validate eventos que se plantea el control seleccionado en ese momento. Esto es por diseño. La interacción con menús y barras de herramientas no hace que el control seleccionado actualmente pierda el foco, lo que significa que la validación nunca se desencadena.

Si lo piensas detenidamente, esto incluso tiene sentido. Imagine que su lógica de validación requiere que cada celda contenga un valor (es decir, evita que las celdas se queden en blanco o vacías). Si el evento de validación se activara cada vez que un usuario intentara seleccionar un elemento de un menú o barra de herramientas, ¡ni siquiera podría "Pegar" nada en la celda!

Tendrá que añadir un montón de lógica fea y adicional a su formulario si insiste en anular este comportamiento y corre el riesgo de molestar seriamente a su usuario. Baste decir que no lo recomiendo.

La mejor solución es extraer su lógica de validación en un método separado, y llamarla manualmente al comienzo del método del controlador de eventos para cada elemento de menú/tirada de herramientas que desea activar la validación. De forma alternativa, puede plantear el evento LostFocus para su control DataGridView al principio de su controlador de evento de clic en el botón Guardar tira usando el InvokeLostFocus method. Algo así como:

InvokeLostFocus(myDataGridView, EventArgs.Empty) 
0

Mientras que la validación se produce en los controles como el TextBox justo después del evento Leave se dispara, el control DataGridView sólo realiza la validación, mientras que en el modo de edición, y sólo en función de cada célula.

Puede manejar el evento CellValidating en el DataGridView para capturar el momento en que la celda actual se valida - este evento se activará si el foco se mueve desde la cuadrícula al botón de guardar. Si el valor de la celda no es válido, puede establecer la propiedad Cancel en el objeto DataGridViewCellValidatingEventArgs en true.

+0

Si bien todo esto es correcto, aún no resuelve el problema del que pregunta. Al hacer clic en un elemento 'ToolStrip' no se activarán los eventos de validación porque la celda seleccionada actualmente permanece seleccionada. Ver mi respuesta para más detalles. –

+0

Ah sí, debería haberme dado cuenta de eso. Estaba explotando ese mismo comportamiento recientemente para implementar un control desplegable personalizado: P –

1

Para mí, llamando a la función "Validar" Formulario de mi desde el interior de evento de clic del menú era suficiente para hacer lo que necesitaba, que incluía obligar a eventos de validación de la cuadrícula para disparar.

+1

Validar() no funcionaba para mí, pero ValidateChildren() sí. Quizás no sea la solución más limpia, pero la única forma en que he podido obligar a la grilla a validar sin intentar cambiar las celdas de forma programática, que sería una solución aún peor. – JPProgrammer

0

Tuve el mismo problema y ninguna de las respuestas en varios foros me funcionó. En mi caso, tenía múltiples cuadrículas en el formulario. E incluso algunas grillas dentro de otros UserControls.Así que creé las siguientes rutinas y llamé a CommitGridEdit() en los eventos de clic relevantes de ToolStrip. Parece hacer el truco para mí.

Public Sub CommitGridEdit(ByVal frm As Form) 
    ' Clicking on a ToolStrip menu item will not cause the grid to end editting the current cell. 
    ' So we have to find if any grid is in edit mode and do this ourself. 
    Dim grid As DataGridView = GetFocusedGrid(frm) 

    If grid Is Nothing Then Exit Sub 

    If Not grid.CurrentCell Is Nothing Then 
     If grid.CurrentCell.IsInEditMode Then 
      grid.EndEdit() 
     End If 
    End If 
End Sub 

Private Function GetFocusedGrid(ByVal ctl As Control) As DataGridView 
    For Each c As Control In ctl.Controls 
     If TypeOf c Is DataGridView AndAlso c.ContainsFocus Then 
      Return c 
     ElseIf c.Controls.Count > 0 Then 
      Dim c2 As Control = GetFocusedGrid(c) 
      If Not c2 Is Nothing Then Return c2 
     End If 
    Next c 
    Return Nothing 
End Function 
Cuestiones relacionadas