从另一个窗体更新对话框 [英] Updating a dialog from another form

查看:207
本文介绍了从另一个窗体更新对话框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道有很多类似的问题,我已经阅读了很多他们。不幸的是,我仍然无法通过阅读解决我的问题 - 但是我对C#来说比较新。根据,而不是 Show()对话框显示得很好,但是随着API文档指出


您可以使用此方法在
应用程序中显示模态对话框。当调用此方法时,它后面的代码不会执行
,直到对话框关闭后


我想要什么,特别是因为这意味着对话更新只会在再次关闭之后发生。



我在这里做错什么?这似乎是一个微不足道的问题,但解决方案逃避了我。请记住,我是C#GUI编程的新手。



此外,我想问一下使用Invoke()的正确的地方?在调用对话方法或者对话框更新方法本身的时候,你会以主窗体的形式使用它吗?

解决方案

看起来你在这里使用多个线程,所以调用的东西不是必需的。调用只需要进行跨线程调用 - 您正在创建多个表单,但所有代码都以相同的线程运行。



如果您正在开展工作主要的UI线程(由代码在按钮点击事件中暗示),然后定期调用 Application.DoEvents()以允许进度表单刷新。 p>

更好的解决方案是使用 BackgroundWorker ,并定期报告其进度。



然后,您可以在BackgroundWorker的 ProgressChanged 事件中更新进度表单(将在主线程中执行,因此您仍然无需调用任何内容)。 p>

I know there are a lot of similar questions out there and I have read through a lot of them. Unfortunately, I still couldn't solve my problem after reading through them - however I am relatively new to C#. According to docs the problem of not being thread safe results in an InvalidOperationException when using the debugger. This is not the case in my problem.

I've recreated the problem with a simple raw test class to concentrate on my problem.

The main form is supposed to show a kind of a progress dialog.

public partial class ImportStatusDialog : Form
{
    public ImportStatusDialog()
    {
        InitializeComponent();
    }

    public void updateFileStatus(string path)
    {
        t_filename.Text = path;         
    }

    public void updatePrintStatus()
    {      
        t_printed.Text = "sent to printer";
    }

    public void updateImportStatus(string clientName)
    {
        t_client.Text = clientName;
    }

    public void updateArchiveStatus()
    {
        t_archived.Text = "archived";
    }
}

When that code is called without any Invoke() from the main form:

private void button1_Click(object sender, EventArgs e)
    {
        ImportStatusDialog nDialog = new ImportStatusDialog();

        nDialog.Show();

        nDialog.updateFileStatus("test");
        Thread.Sleep(1000);
        nDialog.updateImportStatus("TestClient");
        Thread.Sleep(1000);
        nDialog.updatePrintStatus();
        Thread.Sleep(1000);
        nDialog.updateArchiveStatus();
        Thread.Sleep(1000);

        nDialog.Close();
    }

And even when I call it like this:

private void button3_Click(object sender, EventArgs e)
    {
        ImportStatusDialog nDialog = new ImportStatusDialog();

        nDialog.Show();

        if (this.InvokeRequired)
        {
            this.Invoke((MethodInvoker)delegate
            {
                nDialog.updateFileStatus("Test");
            });
        }
        else
        {
            nDialog.updateFileStatus("Test");
        }

        Thread.Sleep(1000);

        if (this.InvokeRequired)
        {
            this.Invoke((MethodInvoker)delegate
            {
                nDialog.updatePrintStatus();
            });
        }
        else
        {
            nDialog.updatePrintStatus();
        }

        Thread.Sleep(1000);

        if (this.InvokeRequired)
        {
            this.Invoke((MethodInvoker)delegate
            {
                nDialog.updateImportStatus("cName");
            });
        }
        else
        {
            nDialog.updateImportStatus("cName");
        }

        Thread.Sleep(1000);

        if (this.InvokeRequired)
        {
            this.Invoke((MethodInvoker)delegate
            {
                nDialog.updateArchiveStatus();
            });
        }
        else
        {
            nDialog.updateArchiveStatus();
        }

        Thread.Sleep(1000);

        nDialog.Close();
    }

the dialog which looks like this in the designer (in my example)

will be displayed like that:

When I use ShowDialog() instead of Show() the dialog displays correnctly, but as the API Doc points out

You can use this method to display a modal dialog box in your application. When this method is called, the code following it is not executed until after the dialog box is closed

which is not what I want, especially as it would mean that the dialog updating would only happen after it has been closed again.

What am I doing wrong here? This seems to be a trivial problem and yet the solution evades me. Please keep in mind that I am new to C# GUI programming.

Also, I would like to ask what would be the right place for using the Invoke()? Do Would you use it in the main form when calling the dialog methods or rather in the dialog update methods itself?

解决方案

It doesn't look like you're using multiple threads here, so the invoke stuff is not required. Invoke is only needed for cross-thread calls - you are creating multiple forms, but all your code is running in the same thread.

If you're doing your work in the main UI thread (as implied by the code being in a button click event), then just call Application.DoEvents() periodically to allow the progress form to refresh.

A better solution would be to use a BackgroundWorker for your work, and have it report its progress periodically.

Then you can update the progress form in the BackgroundWorker's ProgressChanged event (which will be executed in the main thread, so you still don't have to invoke anything).

这篇关于从另一个窗体更新对话框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆