tags:

views:

18

answers:

1

I have a control in my parent mdi form which I wish to be given the focus if all mdi children have closed. I've tried hooking into the child form's FormClosed event and setting the focus from there but when I test it, my control is not left with focus when I close the mdi child.

Can anyone tell me what I'm missing?

In the sample below, "first focus" gets hit and does its job correctly (if I comment out the first focus line, my tree does not get focus on startup, so it must be doing its job, right?) Unfortunately, even though "second focus" gets hit, my tree does not end up with the focus when I close the child window.

Has focus on startup.

Has focus

Not focussed after closing child window.

No focus


Sample

using System;
using System.Windows.Forms;

namespace mdiFocus
{
   class ParentForm : Form
   {
      public ParentForm()
      {
         IsMdiContainer = true;
         tree = new TreeView();
         tree.Nodes.Add("SomeNode");
         tree.Dock = DockStyle.Left;
         Controls.Add(tree);
      }
      protected override void OnShown(EventArgs e)
      {
         Form child = new Form();
         child.MdiParent = this;
         child.Show();
         child.FormClosed += new FormClosedEventHandler(child_FormClosed);
         tree.Focus(); // first focus works ok
      }
      void child_FormClosed(object sender, FormClosedEventArgs e)
      {
         tree.Focus(); // second focus doesn't seem to work, even though it is hit :(
      }
      TreeView tree;
   }

   static class Program
   {
      [STAThread]
      static void Main()
      {
         Application.Run(new ParentForm());
      }
   }
}
+1  A: 

I repro, smells like the WF logic that hunts for a focusable item is running after the event and messes up the focus. These kind of problems can be elegantly solved by running code after the event is processed by using Control.BeginInvoke(). This worked well:

    private void toolStripButton1_Click(object sender, EventArgs e) {
        Form child = new Form2();
        child.MdiParent = this;
        child.FormClosed += new FormClosedEventHandler(child_FormClosed);
        child.Show();
    }

    void child_FormClosed(object sender, FormClosedEventArgs e) {
        if (this.MdiChildren.Length == 1) {
            this.BeginInvoke(new MethodInvoker(() => treeView1.Focus()));
        }
    }
Hans Passant
Fantastic - worked first time - thank you Hans!
Tim Gradwell
Incidentally, what's with the () => shenanigans? Where can I find out more about this syntax?
Tim Gradwell
It is a lambda expression. Check your favorite C# 3.0 programming book.
Hans Passant