2010-03-23 13 views
54

Tengo un cuadro de diálogo que se muestra con <class>.ShowDialog(). Tiene un botón Aceptar y un botón Cancelar; el botón OK también tiene un controlador de eventos.Impedir que un diálogo se cierre en el controlador de eventos click del botón

Quiero realizar una validación de entrada en el controlador de eventos y, si falla, notificar al usuario con un cuadro de mensaje y evitar que el cuadro de diálogo se cierre. No sé cómo hacer la última parte (evitando el cierre).

Respuesta

38

Teniendo en cuenta que ha especificado quieres un error emergente de diálogo, una forma de hacer esto es para mover su validación en un controlador de OnClosing evento. En este ejemplo, el formulario cerrar se cancela si el usuario responde afirmativamente a la pregunta en el cuadro de diálogo.

private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) 
{ 
    // Determine if text has changed in the textbox by comparing to original text. 
    if (textBox1.Text != strMyOriginalText) 
    { 
     // Display a MsgBox asking the user to save changes or abort. 
     if(MessageBox.Show("Do you want to save changes to your text?", "My Application", 
     MessageBoxButtons.YesNo) == DialogResult.Yes) 
     { 
     // Cancel the Closing event from closing the form. 
     e.Cancel = true; 
     // Call method to save file... 
     } 
    } 
} 

Al establecer e.Cancel = true evitará que se cierre el formulario.

Sin embargo, sería una mejor experiencia de diseño/usuario para mostrar los errores de validación en línea (a través destacando los campos ofensivos de alguna manera, que muestra información sobre herramientas, etc.) y evitar que el usuario seleccione el botón OK en El primer lugar.

+4

que funcionaría ... pero sería una práctica horrible de UI. OP ya ha mostrado un diálogo, ¡y luego arroja otro! Es mucho mejor usar las técnicas de validación de winform existentes. Deshabilitar el botón "Aceptar". – Adrian

+2

@Adrian. Dije "unidireccional";). Todo dependería de la probabilidad y/o gravedad del error. Tendría que ver el diseño del formulario antes de tomar una decisión final. – ChrisF

+0

estoy de acuerdo y acabo de leer el OP de nuevo y vi que quería un diálogo HORRIBLE para aparecer. – Adrian

0

Probablemente pueda verificar el formulario antes de que los usuarios presionen el botón OK. Si esa no es una opción, abra un cuadro de mensaje diciendo que algo está mal y vuelva a abrir el formulario con el estado anterior.

+0

Probablemente se puede comprobar el formulario antes de los usuarios pulsa el botón Aceptar -> ¿Cuándo? Solo puedo verificar cuándo intentan "enviar" (tomando prestada la terminología de la web), de lo contrario será inválido simplemente porque el usuario no haya tenido la oportunidad de completarlo primero. Su segunda sugerencia es bastante difícil de implementar; Esperaba algo más simple (o una forma diferente de hacer lo que estoy tratando de hacer) – qster

2

Puede ver FormClosing forzar el formulario para permanecer abierto. use la propiedad Cancelar del objeto de argumento de evento para eso.

e.Cancel = true; 

y debe detener su forma de cierre.

4

Esto no responde directamente a su pregunta (otras ya lo han hecho), pero desde el punto de vista de la usabilidad, preferiría que el botón ofensor se deshabilitara mientras la entrada no fuera válida.

+0

Bueno, sí, pensé en eso, pero cuando una entrada en particular contiene un valor no válido, está claramente marcado con un fondo rojo ... Creo que es suficiente incluso si la desactivación del botón es trivial de implementar, supongo, y no hay lados negativos que hacer – qster

+0

El problema con este enfoque es que para formularios más complicados puede que no sea obvio para el usuario lo que debe hacer para habilitar nuevamente el botón. Este tipo de validación sobre la marcha funcionaría mejor en conjunción con otras cosas, como ErrorProviders, etc. – dreamlax

12

No utilice el evento FormClosing para esto, usted querrá que el usuario pueda cerrar el diálogo con cualquiera Cancelar o haciendo clic en la X. Simplemente implementar controlador de eventos Click del botón OK y don' t cierre hasta que esté satisfecho:

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

Donde "ValidateControls" es su lógica de validación. Devuelve falso si hay algo mal.

+0

Un pequeño detalle: esto supone que no ha especificado DialogResult: OK como parte de la configuración del tiempo de diseño del OK botón. – RenniePet

+1

Luego, haga lo contrario, configurándolo en Ninguno cuando la validación falla. –

3

Usar este código:

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

El problema de esto es que el usuario tiene que dos veces clic en los botones para el cierre de las formas;

121

Puede cancelar el cierre configurando el Formulario DialogResult en DialogResult.None.

Un ejemplo donde button1 es la AcceptButton:

private void button1_Click(object sender, EventArgs e) { 
    if (!validate()) 
    this.DialogResult = DialogResult.None; 
} 

Cuando el usuario hace clic en el botón 1 y el método de validación devuelve falso, la forma no se cerrará.

+0

¿No sería necesario también agregar 'else DialogResult = DialogResult.OK' para que cuando corrijan sus errores y presionar OK la próxima vez que el resultado del diálogo se configure correctamente? – krillgar

+1

Como AcceptButton es el botón 1, DialogResult siempre se establece en DialogResult.OK cuando se hace clic en él. – Arjan

+1

Oh, claro. Eso no anula el DialogResult del botón, simplemente lo cambia en esa rama de la lógica. – krillgar

0

Sólo tiene que añadir una línea en la función de eventos

private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) 
      { 
       this->DialogResult = System::Windows::Forms::DialogResult::None; 
      } 
0
void SaveInfo() 
{ 
blnCanCloseForm = false; 
Vosol[] vs = getAdd2DBVosol(); 
if (DGError.RowCount > 0) 
return; 

Thread myThread = new Thread(() => 
{ 
this.Invoke((MethodInvoker)delegate { 
    picLoad.Visible = true; 
    lblProcces.Text = "Saving ..."; 
}); 
int intError = setAdd2DBVsosol(vs); 
Action action = (() => 
{ 
    if (intError > 0) 
    { 
     objVosolError = objVosolError.Where(c => c != null).ToArray(); 
     DGError.DataSource = objVosolError;// dtErrorDup.DefaultView; 
     DGError.Refresh(); 
     DGError.Show(); 
     lblMSG.Text = "Check Errors..."; 
    } 
    else 
    { 
     MessageBox.Show("Saved All Records..."); 
     blnCanCloseForm = true; 
     this.DialogResult = DialogResult.OK; 
     this.Close(); 
    } 

}); 
this.Invoke((MethodInvoker)delegate { 
    picLoad.Visible = false; 
    lblProcces.Text = ""; 
}); 
this.BeginInvoke(action); 
}); 
myThread.Start(); 
} 

void frmExcellImportInfo_FormClosing(object s, FormClosingEventArgs e) 
{ 
    if (!blnCanCloseForm) 
     e.Cancel = true; 
} 
Cuestiones relacionadas