Phil Wright
Phil Wright

Reputation: 22906

How track when any child control gets or loses the focus in WinForms?

I have a Windows Forms custom control which acts like a panel in that it can contain any number of children. The number and type of the child controls are determined at runtime and so I need to work in a generic manner without knowing the exact child controls that might or might not be present.

I want to alter the background color of my panel depending on if the panel contains the focus. So if a child of the panel (or a child of a child of the panel etc...) takes the focus I want to know this so I can update the background color of the custom panel. When the focus shifts away to something that is not in the child hierarchy then I also need to know so I can revert to the original background color.

The Control.ContainsFocus is great for telling me if the panel contains the focus in the child hierarchy but I need to know when there is a change. At the moment I can only come up with the following poor mechanism.

I hook into the GotFocus/LostFocus of each child and each child of each child etc. I also have to hook the ControlAdded/ControlRemoved to ensure I keep in sync with the possible changing child hieararchy. As you can see this might end up with ALOT of event hooks and I suspect there must be an easier approach. Any ideas?

Upvotes: 2

Views: 5984

Answers (2)

uglycoyote
uglycoyote

Reputation: 1695

Seems like using the Enter and Leave events are the answer. GotFocus will only be sent to the specific control that gains focus, whereas the Enter event will also be sent to the parent (and ancestor) controls of the control that gets the GotFocus event.

from http://msdn.microsoft.com/en-us/library/system.windows.forms.control.leave.aspx

"The Enter and Leave events are hierarchical and will cascade up and down the parent chain until the appropriate control is reached. For example, assume you have a Form with two GroupBox controls, and each GroupBox control has one TextBox control. When the caret is moved from one TextBox to the other, the Leave event is raised for the TextBox and GroupBox, and the Enter event is raised for the other GroupBox and TextBox."

Upvotes: 8

Frans Bouma
Frans Bouma

Reputation: 8357

I'm afraid that's the only option. Winforms has some annoying holes in its api sometimes. I haven't checked but it wouldn't surprise me if ContainsFocus is simply a recursive traversal of the control tree of a container control to see if any control has the focus.

Having a lot of event handlers is not that much of a problem, raising a lot of events which change UI elements is. You could work around this by subsclassing the controls which are addable (but I'm not sure if you have to allow all controls or just a subset) and pass the panel to the control added so the control itself calls into the panel when it gets/loses focus. But that's also a lot of work and the observer-like pattern of having the code in the panel is IMHO easier to do.

Upvotes: 1

Related Questions