防止对话框在按钮的单击事件处理程序中关闭

Posted

技术标签:

【中文标题】防止对话框在按钮的单击事件处理程序中关闭【英文标题】:Preventing a dialog from closing in the button's click event handler 【发布时间】:2011-01-30 18:36:32 【问题描述】:

我有一个用<class>.ShowDialog() 显示的对话框。它有一个确定按钮和一个取消按钮; OK 按钮也有一个事件处理程序。

我想在事件处理程序中进行一些输入验证,如果失败,通过消息框通知用户并阻止对话框关闭。我不知道如何做最后一部分(防止关闭)。

【问题讨论】:

【参考方案1】:

您可以在用户点击 OK 按钮之前检查表单。如果这不是一个选项,则打开一个消息框,说明出现问题并重新打开以前状态的表单。

【讨论】:

您可能可以在用户点击确定按钮之前检查表单 --> 什么时候?我只能检查他们何时尝试“提交”(借用网络术语)它,否则它会因为用户没有机会先填写而无效。您的第二个建议实施起来相当困难;我希望有一些更简单的东西(或者一种不同的方式来做我想做的事情)【参考方案2】:

鉴于您已指定需要弹出错误对话框,执行此操作的一种方法是将验证移至 OnClosing 事件处理程序。在此示例中,如果用户对对话框中的问题回答“是”,则表单关闭将中止。

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

通过设置e.Cancel = true,您将阻止表单关闭。

但是,内联显示验证错误会是更好的设计/用户体验(通过以某种方式突出显示违规字段,显示工具提示等)并阻止用户首先选择“确定”按钮。

【讨论】:

【参考方案3】:

您可以捕获 FormClosing 并强制表单保持打开状态。 为此使用事件参数对象的 Cancel 属性。

e.Cancel = true;

它应该会阻止你的表单关闭。

【讨论】:

【参考方案4】:

这并不能直接回答您的问题(其他问题已经有),但从可用性的角度来看,我希望在输入无效时禁用违规按钮。

【讨论】:

嗯,是的,我想到了,但是当一个特定的输入包含无效值时,它会用红色背景清楚地标记出来。我认为即使禁用按钮实现起来很简单也足够了,我猜,而且没有缺点 这种方法的问题在于,对于更复杂的表单,用户可能不清楚他们需要做什么才能再次启用按钮。这种即时验证与其他事物(例如 ErrorProviders 等)结合使用会更好。【参考方案5】:

我希望我有时间找到一个更好的例子,但你最好使用现有的 Windows 窗体验证技术来做到这一点。

http://msdn.microsoft.com/en-us/library/ms229603.aspx

【讨论】:

【参考方案6】:

不要为此使用 FormClosing 事件,您需要允许用户通过 Cancel 或单击 X 来关闭对话框。只需实现 OK 按钮的 Click 事件处理程序,在您满意之前不要关闭:

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

“ValidateControls”是您的验证逻辑。如果有问题返回 false。

【讨论】:

一个小细节 - 这确实假设您没有指定 DialogResult : OK 作为 OK 按钮的设计时设置的一部分。 然后你做相反的事情,当验证失败时将其设置为 None。 虽然其他答案有帮助,但这是第一个按要求回答问题的人 我正在寻找一种方法来阻止 OK 操作完成。这个答案中的信息让我自己弄清楚。【参考方案7】:

使用此代码:

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

问题是用户必须点击两次按钮才能关闭表单;

【讨论】:

【参考方案8】:

您可以通过将表单的DialogResult 设置为DialogResult.None 来取消关闭。

button1 为 AcceptButton 的示例:

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

当用户点击button1并且validate方法返回false时,表单不会被关闭。

【讨论】:

是否还需要添加else DialogResult = DialogResult.OK 以便在他们修复错误并在下次正确设置对话框结果时点击确定? 因为AcceptButton是button1,所以DialogResult在点击的时候总是设置为DialogResult.OK。【参考方案9】:

只需在事件函数中添加一行

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) 
             
                this->DialogResult = System::Windows::Forms::DialogResult::None;
             

【讨论】:

用户纠正错误后是否需要恢复对话结果?【参考方案10】:
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;

【讨论】:

以上是关于防止对话框在按钮的单击事件处理程序中关闭的主要内容,如果未能解决你的问题,请参考以下文章

通过单击事件处理程序防止 routerLink 更改路由

选择日期后,日期选择器应在 android 中关闭,而无需单击确定按钮

如何防止点击事件传播

防止对话框在 Flutter 中关闭外部触摸

如何在 Expression Blend 中的单个事件处理程序中为按钮单击添加多个事件?

如何删除“按钮”的“单击”事件的所有事件处理程序?