以异步方式打开第二个winform,但仍然表现为父表单的子项?

时间:2010-03-12 20:42:57

标签: c# winforms

我正在创建一个应用程序,我希望实现一个进程窗口,该窗口在进行冗长的过程时出现。

我创建了一个标准的Windows窗体项目,我使用默认窗体创建了我的应用程序。我还创建了一个新表单作为进度窗口。

当我使用:

打开进度窗口(在函数中)时出现问题
ProgressWindow.ShowDialog();

当遇到这个命令时,焦点在进度窗口上,我认为它现在是正在为事件处理主循环的窗口。缺点是它阻止了我在主窗体中执行冗长的操作。

如果我使用以下方式打开进度窗口:

ProgressWindow.Show();

然后窗口打开正确,现在不会阻止主窗体的执行,但它不作为子窗口(模态)应该,即允许选择主窗体,不以父窗口为中心等等。

我是如何打开新窗口但继续以主窗体处理的想法?

3 个答案:

答案 0 :(得分:11)

您可能在单独的工作线程中开始冗长的操作(例如,使用后台工作程序)。然后使用ShowDialog()显示您的表单,并在完成该主题后关闭您正在显示的对话框。

以下是一个示例 - 我假设您有两种形式(Form1Form2)。在Form1我从工具箱中提取了BackgroundWorker。然后我将RunWorkerComplete的{​​{1}}事件连接到我表单中的事件处理程序。以下是处理事件并显示对话框的代码:

BackgroundWorker

答案 1 :(得分:3)

另一种选择:

使用ProgressWindow.Show()&自己实现模态窗口行为。 parentForm.Enabled = false,自己定位表单等。

答案 2 :(得分:3)

我为另一个项目实现了与此类似的东西。此表单允许您从工作线程中弹出模式对话框:

public partial class NotificationForm : Form
{
    public static SynchronizationContext SyncContext { get; set; }

    public string Message
    {
        get { return lblNotification.Text; }
        set { lblNotification.Text = value; }
    }

    public bool CloseOnClick { get; set; }

    public NotificationForm()
    {
        InitializeComponent();
    }

    public static NotificationForm AsyncShowDialog(string message, bool closeOnClick)
    {
        if (SyncContext == null)
            throw new ArgumentNullException("SyncContext",
                                            "NotificationForm requires a SyncContext in order to execute AsyncShowDialog");

        NotificationForm form = null;

        //Create the form synchronously on the SyncContext thread
        SyncContext.Send(s => form = CreateForm(message, closeOnClick), null);

        //Call ShowDialog on the SyncContext thread and return immediately to calling thread
        SyncContext.Post(s => form.ShowDialog(), null);
        return form;
    }

    public static void ShowDialog(string message)
    {
        //Perform a blocking ShowDialog call in the calling thread
        var form = CreateForm(message, true);
        form.ShowDialog();
    }

    private static NotificationForm CreateForm(string message, bool closeOnClick)
    {
        NotificationForm form = new NotificationForm();
        form.Message = message;
        form.CloseOnClick = closeOnClick;
        return form;
    }

    public void AsyncClose()
    {
        SyncContext.Post(s => Close(), null);
    }

    private void NotificationForm_Load(object sender, EventArgs e)
    {
    }

    private void lblNotification_Click(object sender, EventArgs e)
    {
        if (CloseOnClick)
            Close();
    }
}

要使用,您需要从GUI线程中的某个位置设置SyncContext:

NotificationForm.SyncContext = SynchronizationContext.Current;