为Form_Find实现正确的GUI行为

时间:2014-12-19 08:11:14

标签: c# .net winforms user-interface

我有一个简单的应用程序,包含2个表单: Form_Main和Form_Find。

Form_Main 是一个包含网格的大表单, Form_Find 是一个小型表单,上面有一个TextBox和2个按钮(“Previous”,“Next”)。

Form_Find仅在用户按下Ctrl-F后显示。

到目前为止一切顺利,我只留下一个问题, 与GUI有关的问题。

问题在于:

Form_Find的 .TopMost 属性设置为True。

当我在申请时,它非常有效, 但是当我打开应用程序并切换到另一个应用程序(例如浏览器)时,Form_Main被新窗口(例如浏览器)覆盖,就像它应该的那样, 但是Form_Find仍然是浮动和显示的,覆盖了另一个应用程序窗口的一部分,并且令人不安。

我希望Form_Find以某种方式成为Form_Main的孩子, 所以如果我离开/最小化Form_Main,那么Form_Find将不会继续出现.. 并且只有在我回到申请表后才会重新出现 - 到Form_Main。

为此,我将Form_Find的 .Parent 属性设置为Form_Main的实例, 为了使它工作,我还需要在它之前写一行,它将Form_Find的 .TopLevel 属性设置为false。 (否则我无法将父设置为Form_Find)

这实际上有效, 现在,Form_Find的行为类似于Form_Main的子形式: 当我从我的应用程序切换到另一个应用程序时,Form_Main和Form_Find都被新的应用程序窗口覆盖。

所以这个问题确实解决了, 然而,由于它引发了一个新的问题,这个新问题就是我现在所困扰的问题。

新问题是:

每当我点击Form_Find中的“下一步”按钮时, 它导致Form_Main上的Grid控件失去焦点。 当Form_Main上的Grid失去焦点时,Grid会从EditMode中获取EditMode中的单元格。

这是我的问题。

在将Form_Main设置为Form_Find的Parent之前,没有发生这种情况。 它没有发生的原因是因为当Form_Find不是Form_Main的孩子时, 然后当Form_Find聚焦时,Form_Main中的焦点控件永远不会知道它。 Form_Main可能会失去焦点到另一种形式,但Form_Main中的控件将永远不会知道它,并且永远不会触发任何相关的事件(只有表单)。

所以你看, 使Form_Find的行为很好, 我需要这两件事:

1)让Form_Find以某种方式成为Form_Main的子节点,所以当我切换到另一个窗口时,Form_Find将不会继续浮动在屏幕上,覆盖其他应用程序 2)当我单击Form_Find上的“下一步”按钮时,让Form_Find不从Form_Main上的焦点控件中窃取焦点。只要Form_Find不是Form_Main的孩子,我确实有这个,但是一旦我成功使Form_Find成为Form_Main的孩子,我就失去了这个。

所以我向你提问: 这个问题的解决方案是什么?

非常感谢

1 个答案:

答案 0 :(得分:1)

要确定所要求的正确父/子行为,您需要在打开孩子时将所有者表单传递给孩子。

可以使用LinqPad来测试此概念证明 (*我没有与他们有任何关系,恕我直言,它只是你需要的最有用的工具)

Form f1;
void Main()
{
    f1 = new Form();
    TextBox t1 = new TextBox();
    t1.Location = new Point(0,0);
    TextBox t2 = new TextBox();
    t2.Location = new Point(0,30);
    f1.Controls.AddRange(new Control[] {t1,t2});
    f1.Deactivate += onDeactive;
    f1.Show();

    Form f2 = new Form();
    Button b = new Button();
    b.Click += bClick;
    f2.Controls.Add(b);

    // This line pass the F1 form
    // as owner of F2 establishing the 
    // correct parent/child behavior
    f2.Show(f1);
}

void bClick(object sender, EventArgs e)
{
    Console.WriteLine("Clicked");
    f1.ActiveControl.Text = DateTime.Now.ToString("hh:mm:ss");
}
void onDeactive(object sender, EventArgs e)
{
    Console.WriteLine("Main Deactivated");
}