【问题标题】:Using DialogResult Correctly正确使用 DialogResult
【发布时间】:2013-05-26 15:25:30
【问题描述】:

在回答我最近的一个问题 (Here) 时,Hans Passant 表示我应该设置 DialogResult 而不是 form.Close() 来关闭我的表单,尽管我似乎无法找出原因?

如果我没看错,MSDN 文档指出这样做只会隐藏表单,而不是像我认为 .Close() 那样正确处理它?

Extract 来自文档。

当用户单击对话框的关闭按钮或设置 DialogResult 属性的值时,不会自动调用 Close 方法。相反,该表单被隐藏并且可以再次显示而无需创建对话框的新实例。由于这种行为,当您的应用程序不再需要该表单时,您必须调用该表单的 Dispose 方法。

另一方面,Microsoft 创建了一个support page,说明如何使用 DialogResult 属性,并在“验证它的工作原理”部分中声明单击该属性将关闭表单。

所以我的问题有两个,我应该继续使用 Close 还是 DialogResult ;并且对话框结果是否关闭或隐藏表单。从我在下面制作的代码(一个带有两个按钮的简单表单)来看,它似乎确实只是隐藏在this.Close() 上的断点被击中..(this.Close() 评论,表单仍然消失,只是不确定是否隐藏)

    public Form1()
    {
        InitializeComponent();
        button1.Click += (s, e) =>
            {
                 //I edited my question to include using
                using(Form1 form = new Form1())
                {
                    form.ShowDialog();
                }

            };
        button2.Click += (s, e) => 
            {
                this.DialogResult = DialogResult.OK;
                this.Close();
            };
    }

【问题讨论】:

    标签: c# winforms dialogresult


    【解决方案1】:

    您是否调用Close 或设置DialogResult 属性并不是真正的问题。您只需要确保致电Dispose。我更喜欢使用 using 块:

    using (Form1 form = new Form1())
    {
        form.ShowDialog();
    }
    

    我原本以为你可以在已经调用了Close 方法的Form 上调用ShowDialog。不是这种情况。如果您使用ShowDialog 以模态方式显示表单,它是否由于Close 方法或设置DialogResult 属性而关闭似乎并不重要。设置DialogResult 似乎只是关闭Form 的捷径。

    但是无论您调用Close 还是设置DialogResult 属性,关键是确保您调用Dispose() 或将您的表单放在 using 块中。

    【讨论】:

    • 上面的代码显然只是我匆忙写的一个例子,而且我确实倾向于使用using 语句,只是不知道为什么我应该使用 DialogResult 而不是 this.Close() , 是否像知道表单被取消或确定一样简单?
    • 我用this.Close 尝试了你的例子,如我的例子所示,我仍然能够重用它看起来的表单......
    • @Sayse 我刚刚查看了文档(应该是我的第一步)。它表示如果使用ShowDialog 显示表单,则不会调用Close。我很惊讶。看起来并不重要。
    • @Dan - 我认为你夸大了调用 Dispose 的有用性(或放置在“使用”语句中)。与 .Net 中的任何其他对象一样,一旦没有对表单的可访问引用,它将(最终)被垃圾收集。恕我直言,显式 Dispose 仅​​在表单包含需要及时释放的重要资源时才重要。
    • 我真的不想为此争论,尤其是因为我认为 WinForms 早已死去,所以我将放弃。但是问这个:如果Dispose不需要被调用,那为什么还要实现IDisposable呢?
    【解决方案2】:

    当您使用 ShowDialog 打开模式对话框时,调用代码将被阻止,直到被调用的窗体关闭或隐藏。如果您想读取被调用表单的一些公共属性,并希望通过单击“确定”或“取消”按钮来执行操作(例如将数据保存到数据库或文件中),那么您需要知道用户是否想要做或不做动作。 ShowDialog() 方法返回的 DialogResult 允许您采取适当的操作...

    例如

    using (Form1 form = new Form1())
    {
        DialogResult dr = form.ShowDialog();
        if(dr == DialogResult.OK)
        {
            string custName = form.CustomerName;
            SaveToFile(custName);
        }
        
    }
    

    要添加到此答案中的重要一点是 DialogResult 属性同时存在于 Form 类和 Button 类中。将按钮的 DialogResult 属性(通过代码或设计器)设置为不同于DialogResult.None 的值是激活表单重要行为的关键。如果您单击设置了该属性的按钮,则表单引擎会将 Buttons 属性的值传输到 Forms 并触发表单的自动关闭,从而重新激活调用者代码。如果您在按钮单击上有一个事件处理程序,那么您可以运行代码来验证表单的输入并强制表单保持打开状态,覆盖表单的 DialogResult 属性,将其设置回 DialogResult.None

    例如,在模态显示的表单中,您可以:

    // Event handler for the OK button set with DialogResult.OK
    public void cmdOK_Click(object sender, EventArgs e)
    {
         // Your code that checks the form data and
         // eventually display an error message.
         bool isFormDataValid = ValidateFormData();
    
         // If data is not valid force the form to stay open
         if(!isFormDataValid)
            this.DialogResult = DialogResult.None;
    }
    

    【讨论】:

    • 我刚刚扩展了我的示例代码以包含与您展示给我的内容类似的内容,并且仍然存在this.Close(),我可以访问表单属性,您的意思是有可能这是不是这样吗?
    • 不,我已将答案修正为更专注于 ShowDialog 返回的 DialogResult 所发挥的功能。 (真的很接近不要调用 Dispose ,因此您仍然可以阅读表单的公共属性)
    • 我是否正确地认为支持 DialogResult 的想法是让您可以根据对话结果将其用于进一步的逻辑? (我总是在需要时同时包含 DialogResult 和 Form.Close())
    • @Sayse 是的,你是对的。我们正在处理两个不同的概念。 Dispose() 概念是使用 using 处理的,正如这里的两个答案一样。另一个概念是DialogResult 的设置,以指示对话框关闭的方式——因此启动对话框的代码可以告诉如何在必要时做出响应。通常您可能会忽略结果,但这取决于对话框的创建者。该对话框应始终报告关闭的原因,以便为创建者提供该选项。 (如果它只有一个退出状态,那么c没关系)
    • 我玩过这个,似乎当你设置 DialogResult 时,它似乎没有任何效果,直到表单的消息循环从处理 Windows 消息返回。例如,如果您在表单的构造函数中执行此操作:Task.Run(() => {Thread.Sleep(1000);this.DialogResult = DialogResult.Cancel;}); 如果您将鼠标远离表单,则不会发生任何事情,但是当您将鼠标悬停在表单上时,它会突然关闭。
    猜你喜欢
    • 2011-09-10
    • 1970-01-01
    • 1970-01-01
    • 2019-03-22
    • 2012-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-19
    相关资源
    最近更新 更多