【问题标题】:Modal-like User Control模态用户控制
【发布时间】:2017-09-13 17:26:49
【问题描述】:

我有一个使用拆分容器的多标签 Winform。在右侧选项卡中,我使用左侧选项卡显示/隐藏用户控件。一些用户控件需要在其上显示一个新的用户控件。问题是当原始用户控件显示新用户控件时,我希望第一个用户控件等待新用户控件关闭(有些像表单中的 ShowDialog),但是这个屏幕锁定应该只出现在一个选项卡中。

我尝试了 Threads 和许多其他解决方案,但没有一个能如我所愿。

{
    var panel = (Panel)this.Parent;
    var searchUserControl = new searchUserControl();
    searchUserControl.Parent = this;
    panel.Controls.Add(searchUserControl);
    this.visible = false; // hides the original form
    // wait
    this.visible = true; // shows the original form again
    var result = searchUserControl.CustomProperty;
}

【问题讨论】:

  • 你不能禁用第一个用户控件,直到完成第二个?
  • 不会等待代码
  • 啊,我想我明白你现在的要求了。您希望ShowDialogUserControl 类似,但仅限于一个标签页,您仍然希望能够在“对话框控件”启动时将标签更改为其他页面。您还想在“对话框控件”打开的位置阻止代码执行,以便它仅在控件关闭时运行下一行,大概返回某种“结果代码”,就像对话框一样。对吗?
  • 我也许可以使用async/await 来安装类似的东西,但是你们其余的代码必须支持它(一路异步)。
  • @BradleyUffner 就是这样。我来自网络世界,并锁定了这个。我无法使用 ShowDialog 阻止所有主要表单,但我需要打开一个模式“搜索”到特定容器。

标签: c# winforms


【解决方案1】:

如果您使用一些技巧,您可以使用async/await 来做到这一点。

关键成分是TaskCompletionSource。它代表Task 的“状态”,并允许您从代码中的另一个点“完成”它,在本例中,是“对话框”上的一个按钮。

创建一个UserControl 来代表您的“对话”,给它“确定”和“取消”按钮,或者您需要的任何按钮。

UserControl 的代码隐藏应如下所示:

public partial class DialogControl : UserControl
{
    TaskCompletionSource<DialogResult> _tcs;

    public DialogControl()
    {
        InitializeComponent();
        this.Visible = false;
    }

    public Task<DialogResult> ShowModalAsync()
    {
        _tcs = new TaskCompletionSource<DialogResult>();

        this.Visible = true;
        this.Dock = DockStyle.Fill;
        this.BringToFront();
        return _tcs.Task;
    }

    private void btmCancel_Click(object sender, EventArgs e)
    {
        this.Visible = false;
        _tcs.SetResult(DialogResult.Cancel);
    }

    private void btnOk_Click(object sender, EventArgs e)
    {
        _tcs.SetResult(DialogResult.OK);
        this.Visible = false;
    }

    public string UserName
    {
        get { return txtName.Text; }
        set { txtName.Text = value; }
    }
}

主窗体上的Button可以使用此代码显示“模态控件”:

private async void btnShowDialogControl_Click(object sender, EventArgs e)
{
    var control = new DialogControl();
    splitContainer1.Panel2.Controls.Add(control);

    //Disable your other controls here


    if (await control.ShowModalAsync() == DialogResult.OK) //Execution will pause here until the user closes the "dialog" (task completes), just like a modal dialog.
    {
        MessageBox.Show($"Username: {control.UserName}");
    }

    //Re-enable your other controls here.

    splitContainer1.Panel2.Controls.Remove(control);
}

工作解决方案的完整源代码可以从here下载。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多