【问题标题】:Replacing ShowDialog() with Show()用 Show() 替换 ShowDialog()
【发布时间】:2019-06-25 01:55:07
【问题描述】:

我有一个使用 ShowDialog() 显示的表单,因此它是一个模式窗口。

private void OpenForm(object sender, ItemClickEventArgs e)
{
    MyForm testForm = new MyForm();
    ...
    testForm.Enabled = true;
    testForm.ShowDialog(this);
    var dialogOk = testForm.DialogOK;
    if(dialogOk)
    {
       //do some stuff 1
    }
}

表单上有一个“确定”按钮。单击确定时,DialogOk 设置为 true。 MyForm 类内部:

private void OkClick(object sender, EventArgs e)
{
   // do some stuff 2
   ... 
   DialogOK = true;
   Hide();
}

我需要将其转换为非模态窗口。解决方案似乎是使用 Show() 而不是 ShowDialog(),但是当我使用 Show() 时,代码不会停止并等待单击 OK 按钮,因此永远不会调用“do some stuff 1”。

使用 Show(),如何在单击 OK 按钮后保持“做一些事情 1”的行为?

更新:这是我现在正在尝试的:

public partial class MyForm: XtraForm
{
   public bool DialogOk;

   private void OkClick(object sender, EventArgs e)
   {
      // do some stuff 2
      ... 
      DialogOk = true;
      Close();
   }
}

方法一:

public partial class MyMainForm : XtraForm
{
   private MyForm testForm;

   private void OpenForm(object sender, ItemClickEventArgs e)
    {
        if(testForm == null)
        {
            testForm = new MyForm();
        }
        ...
        testForm.Enabled = true;
        testForm.FormClosed += (s, a) => {
            var dialogOk = testForm.DialogOk;
            if (dialogOk)
            {
                // do some stuff 1
            }
        };
        testForm.Show(this);
    }
}

方法二:

public partial class MyMainForm : XtraForm
{
       private MyForm testForm;

       private void OpenForm(object sender, ItemClickEventArgs e)
        {
            if(testForm == null)
            {
                testForm = new MyForm();
            }
            ...
            testForm.FormClosed += testForm_Closed;
            testForm.Show(this);
        }

        private void testForm_Closed(object sender, EventArgs args)
        {
            var testForm = (Form)sender;
            testForm.Closed -= testForm_Closed;

            if (testForm.DialogResult == DialogResult.OK)
            {
               // do some stuff 1
            }
        }
 }

【问题讨论】:

  • 一种方法是让对话框窗体在单击 OkClick 时调用父窗体(作为参数传递给它)内的方法或事件。
  • 我很困惑。你能解释一下为什么你需要一个非模态窗口来表现得像一个模态窗口吗?听起来您应该保持窗口模式。
  • 由于您想锁定主界面的执行,直到在第二个窗口上单击“确定”按钮,所以在我看来,您需要的实际上是一个模态窗口。
  • @GabrielLuci 我需要能够点击当前模式窗口之外的其他窗口。
  • 顺便说一句,Form 有一个名为 DialogResult 的属性 - 将其设置为 DialogResult.Ok 它将自动隐藏表单并返回值 - 因此您的代码将更改为 if(testForm.ShowDialog(this)==DialogResult.Ok)

标签: c# winforms show showdialog


【解决方案1】:

你可以处理Form.Closed事件:

MyForm testForm = new MyForm();
testForm.Closed += testForm_Closed;
testForm.Show();

private void testForm_Closed(object sender, EventArgs args)
{
    var testForm = (Form)sender;
    testForm.Closed -= testForm_Closed;

    if (testForm.DialogResult == OK)
        // do some stuff 1
}

【讨论】:

  • 当我在表单上单击“确定”时,仍在调用 OkClick(),但未调用 testForm_Closed。你认为我可能遗漏了什么吗?
  • 您需要调用 Close() 而不是 Hide() 才能发生 .Closed 事件
  • @pm101 我将 Hide() 更改为 Close() 但事件仍未发生。
  • 嗯,我做了一个示例项目,效果很好。你能更新你的代码来告诉我们你在做什么新的吗?
  • @pm101 我更新了代码。我尝试使用此评论中的方法和下面的方法。两者都有相同的结果,没有调用委托。
【解决方案2】:

最简单的方法是将代码从OpenForm 移动到事件处理程序OkClick。但是,如果这不是放置代码的好地方,因为您可能希望对不同的任务使用相同的表单,您可以为FormClosed 事件添加一个处理程序,该处理程序在表单关闭并运行代码后调用,例如:

private void OpenForm(object sender, ItemClickEventArgs e)
{
    MyForm testForm = new MyForm();
    ...
    testForm.Enabled = true;
    testForm.FormClosed += (s, a) => {
      var dialogOk = testForm.DialogOK;
      if(dialogOk)
      {
         //do some stuff 1
      }
    };
    testForm.Show(this);
}

【讨论】:

  • 当我尝试执行此操作时,我收到以下错误:“无法在此范围内声明名为‘sender’的本地参数,因为该名称在封闭的本地范围中用于定义本地或参数”
  • 这意味着在封闭方法上已经有一个名为sender的参数。我已将代码更改为仅使用 s 和 a 作为委托的参数名称,以便不再有冲突。
  • 感谢您的澄清。通过此代码更改,当我单击“确定”或关闭表单时,不会触发 FormClosed 事件处理程序。还有什么我可能在这里遗漏的吗?
  • 您应该关闭它而不是隐藏表单。或者您想稍后再次使用同一个实例?
  • 我不需要使用同一个实例。将 Hide() 更改为 Close() 也不能解决问题。
【解决方案3】:

您可以使用与TaskCompletionSource 绑定的异步事件处理程序,它会侦听并等待表单关闭

private asyc void OpenForm(object sender, ItemClickEventArgs e) {
    var source = new TaskCompletionSource<DialogResult>();

    EventHandler handler = null;
    handler = (s, args) => { 
        var  form = (MyForm)s;
        form.FormClosed -= handler;
        source.SetResult(form.DialogResult);
    }

    var testForm = new MyForm();
    testForm.FormClosed += handler; //subscribe
    //...
    testForm.Enabled = true;
    testForm.Show();

    var dialogOk = await source.Task;
    if(dialogOk == DialogResult.Ok) {
       //do some stuff 1
    }
}

这样您就可以将逻辑保留在OpenForm 中,并允许代码等待而不阻塞。

在点击按钮时的表单中,您需要做的就是设置对话框结果并关闭表单。

public partial class MyForm: XtraForm {

    //...

    private void OkClick(object sender, EventArgs e) {
        // do some stuff 2
        // ... 

        DialogResult = DialogResult.Ok;
        Cose();
    }
}

【讨论】:

    【解决方案4】:

    这对我有用,所以不知道为什么它不适合你(抓头)...此表单有两个按钮,一个用于再次打开同一个表单,另一个用于关闭表单。 “父”表单将事件添加到 Closed 事件。

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
            Form1 test = new Form1();
    
            test.FormClosed += Test_FormClosed;
    
            test.Show();
        }
    
        private void Test_FormClosed(object sender, FormClosedEventArgs e)
        {
            MessageBox.Show("closed -- do something else here!");
        }
    
        private void button2_Click(object sender, EventArgs e)
        {
            Close();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-19
      • 2022-08-05
      • 2021-03-28
      • 1970-01-01
      • 2016-02-09
      相关资源
      最近更新 更多